Where is the object that references the #body payload stored?
If your user controller has a post function.
#Post() #HttpCode(HttpStatus.CREATED) create(#Body() user: IUserBase):
Promise { return this.usersService.create(user); }
Where is the user variable stored?
Is it stored in the request object of the nest.js server?
It is injected into the function as an argument.
The #body decorator basically says:
Please cast the json that arrives in the request body into IUserBase type and place it as a parameter to this controller's handler.
Related
I have an API that returns a response with a header, status code, and body field. How do I correctly handle this using retrofit, and Kotlin Coroutines? I'm used to a simple implementation such as below, but this does not work since the API is not just the JSON body.
Typical implementation:
interface MyApi {
#GET("myapi")
suspend fun getData() : DataClass
}
With the following response, the above implementation does not work:
{
statusCode=200.0,
headers={
x-custom-header=my custom header value
},
body={
"name":"John",
"message":"Hello"
}
}
Do I need to create a wrapper class for this new type of response? Then, to access the data just call WrapperClass.body? Or is there a more elegant solution to this?
I have a simple ApolloGateway server, which receives a gql mutation. What I am trying to accomplish is to make another gql mutation upon receiving a success call from the mutation call.
I can see that I can use the method didReceiveResponse in order to handle the received body. However, I am not sure whether there is a better way to do it. Specially, I will need to parse the body, check for the request type, and then make a qgl query, and send an http request, etc.
class SomeRemoteGraphQLDataSource extends RemoteGraphQLDataSource {
async didReceiveResponse(response, req, context) {
const body = await super.didReceiveResponse(response, req, context);
// Do something
return body;
}
}
I am trying to build a decorator to "log" request info
export const Tracking = () => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const method = descriptor.value;
descriptor.value = async function(...args: any[]) {
console.log(/** Request info */)
console.log(/** Headers, Body, Method, URL...*/)
return method.call(this, ...args);
}
}
}
and try to use it on a controller method like this.
export class Controller {
#Get('/path')
#Tracking()
public async getData(#Headers('user') user: User) {
return this.service.getData(user.id);
}
}
If this is impossible, is there a way to apply interceptor to some method of controller?
Or is there a thread(like)-level context for request?
Thanks!!
Decorators don't have access to the request information because of what a decorator is. It's a higher order function that is called to set metadata for the class, class member, class method, or class method parameter. This metadata can be read at runtime, but it is called and set essentially as soon the file is imported. Due to this, there's no way to call a decorator on each request, even Nest's #Body() and #Req() are called at the time of import and read at the time of the request (actually earlier but that's besides the point).
What you're looking for here sounds more like an interceptor, like Micael Levi and hoangdv have already mentioned. The Nest docs show a basic logging example, and there are packages out there like #ogma/nestjs-module (disclaimer: I'm the author) that handle this request logging/tracking for you including the addition of correlation IDs.
In Node js, i am using express validator to validate the request body of an API.
I have one file validators.js where I define validators for an API request.
I want to validate inviteesArray which needs to be in below format:
//expected
[
{"userId" :"07aeb7ff-bf11-4a64-b842-a6fe1aa0a7f6"},
{"userId" :"7b89059a-3915-4d1d-b55c-077260f07021"}
];
my validator:
body('inviteesArray','inviteesArray is required!').if((value, { req }) => req.body.isInvited !== "false").isArray().notEmpty(),
request in postman, which gives validation error, what am I doing wrong?
**UPDATE**
when i change my validator with removing the if condition it works.
body('inviteesArray','inviteesArray is required!').if((value, { req }) => console.log(value)).isArray().notEmpty(),
You hove to add object keys inside braces to pass as an array of object
KEY VALUE
invitesArray[0][userId] first value
invitesArray[1][userId] second value
I am trying to access to Request object from within a Validation Pipe in nestjs
In order to verify uniqueness of certain fields, I require the ID/UUID parameters supplied with PUT/PATCH request (not available in the data structure itself)
any idea?
Currently, it is not possible to access the request object at all in a pipe. If you need the request you can use a guard or an interceptor.
If you are working on verifying uniqueness, that sounds like a part of business logic more than just about anything else, so I would put it in a service and handle the query to the database there. Just my two cents.
Edit 11/17/2020
After learning way more about how the framework works as a whole, technically it is possible to get the entire request object in a pipe. There are two ways to go about it.
Make the pipe #Injectable({ scope: Scope.REQUEST }) so that it is request scoped. This will end up creating a new pipe on each request, but hey, if that's your cup of tea then great.
Make a custom parameter decorator as custom decorators get completely passed into pipes as they are. Do note, that this could impact how the ValidationPipe is functioning if that is bound globally, at the class, or method level.
We can create a Pipe and access request object. We can move further and update the Body as well, if needed.
Following is an example scenario, where createdBy field should be added to the Body dynamically. Let's say user details are available from request:
// user.pipe.ts
import { Request } from 'express'
import { REQUEST } from '#nestjs/core'
import { Injectable, Inject, Scope, PipeTransform } from '#nestjs/common'
#Injectable({ scope: Scope.REQUEST })
export class UserPipe implements PipeTransform<any> {
constructor(#Inject(REQUEST) protected readonly request: Request) {}
transform(value) {
let email = this.request["user"].email;
value['createdBy'] = email;
return value
}
}
We can now use this in controller like this:
// someentity.controller.ts
#Post()
public async create(
#Body(SetUserPipe) dto: SomeEntityDto,
): Promise<SomeEntity> {
....
}