How should I create the dto for the nestjs response?
I am currently creating the following code.
I want to define it like the dto of input parameters.
■ response code like this
return {
statusCode: 200,
message: 'successs',
data: {
id: 10
}
}
■ I want to do like this
async test: Promise<SuccessDto> {
return respoinse: SuccessDto
}
I believe there is no need to do that. You can access the code through the headers and the convention is the following
200 is ok / success,
201 is created,
204 is no response,
400 is bad request,
401 is unauthorized,
403 is forbidden,
404 is not found
But to answer your question, it might be possible through interceptors. Their sandbox :
https://github.com/nestjs/nest/blob/master/sample/21-serializer/src/app.controller.ts
use the Res, create a DTO with a generic or a class to extends it and glue it together. Use the #Type(() => YourDTO) to expose what you need. But your kind of reinventing the wheel, NestJS takes care of it and you can overwrite the Response status if needed.
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'd really like to be able to pass custom errors back out of my Lambda function via the API Gateway.
I'm generating the errors this way:
if (error) { // failure
APIGatewayResult = { // set error object
statusCode: 608,
message: 'File upload to buffer failed.',
error: error
};
done();
};
I'm fairly certain the format above is either parsed incorrectly or I can't pass it back out like this:
done = (err, res) => callback(null, {
statusCode: err ? APIGatewayResult.statusCode : APIGatewayResult.statusCode,
body: err ? JSON.stringify(APIGatewayResult) : JSON.stringify(APIGatewayResult),
headers: {
'Content-Type': 'application/json',
},
});
I'd like the response I get from API gateway to look like this:
{
"statusCode": 608,
"message": "File upload to buffer failed.",
"error": {}
}
Instead of this:
{
"message": "Internal server error"
}
There are two parts to your question:
1) How to handle Lambda error messages in API Gateway:
There are numerous guides available which explain how to parse Lambda error responses in API Gateway to return them in the desired format to consumers. For example: Error Handling Patterns in Amazon API Gateway and AWS Lambda.
Important to note that you're parsing null to the first parameter of the callback function from your lambda. The first parameter is the error response message, so by providing it as null the Lambda will be returning a successful 200 response back to API Gateway.
2) How to override the generic unhandled exception message in API Gateway:
This is required because as mentioned in the comments, the error you're receiving appears to have been thrown due to an unhandled exception in your application. You'll need to review the logs to identify the source of the issue.
But to change the format of the default error response object you'll need to add a custom Gateway response in API Gateway.
It's difficult to offer a more concrete example given the limited information provided but this should be enough to point you in the right direction to find what you're looking for.
This is a function on my front-end that makes the request.
function postNewUser(){
fetch(`http://12.0.0.1:8080/users/test`, {
method: 'POST',
body: {nome: name, email: "test#test.com.br", idade: 20}
})
}
This is my back-end code to receive the request.
router.post('/users/:id', koaBody(), ctx => {
ctx.set('Access-Control-Allow-Origin', '*');
users.push(ctx.request.body)
ctx.status = 201
ctx.body = ctx.params
console.log(users)
})
For some unknown reason I receive nothing. Not even a single error message. The "console.log()" on the back-end is also not triggered, so my theory is that the problem is on the front-end.
Edit
As sugested by gnososphere, I tested with Postman, and it worked. So now i know the problem must be on the fron-end code.
You can try your backend functionality with Postman. It's a great service for testing.
the request would look something like this
If the problem is on the frontend, double check your fetch method by posting to a website that will return data and logging that in your app.
I'm trying to document my api in NestJS. I have followed NestJS documentation and it works very well but I would like to know if there is anyway to separate the swagger decorators from the controller code. Because the api starts to grow, the controller code starts to get a little bit confusing because having the decorators in between the request methods interferes with the way the flow it is seen.
I have used the decorators but when you need in an endpoint guards validation, pipes it gets pretty big and unfocused, because of the amount of decorators that get added and I am not confused swagger is not that important in the actual execution flow as it is guards, validators, etc.
#Post()
#Roles('user')
#ApiResponse({ status: 201, description: 'The token has been successfully created.'})
#ApiResponse({ status: 403, description: 'Forbidden.'})
#UsePipes(new ValidationPipe())
#HttpCode(200)
async createToken(#Body() createTokenDto: CreateTokenDto) {
this.tokenBuilderService.createToken(createTokenDto);
}
Pretty old question but just pointing it out so people will know.
You can separate using the applyDecorators function imported from #nestjs/common which accepts an array of decorators and composes them for you in a single decorator: https://docs.nestjs.com/custom-decorators#decorator-composition
In your example, you could do something like:
// controller.decorator.ts
export function SwaggerDecorator() {
return applyDecorators(
ApiResponse({ status: 201, description: 'The token has been successfully created.' }),
ApiResponse({ status: 403, description: 'Forbidden.' })
);
}
Note that the decorators are without the # symbol.
and import it in the controller file:
import { SwaggerDecorator } from './controller.decorator'
#Post()
#Roles('user')
#SwaggerDecorator()
#UsePipes(new ValidationPipe())
#HttpCode(200)
async createToken(#Body() createTokenDto: CreateTokenDto) {
this.tokenBuilderService.createToken(createTokenDto);
}
I just faced this issue and it cleared A LOT of swagger code in my controllers.
No.You can't separate the swagger decorators from the controller code.
I usually place it at the end to separate them from pipes and guards:
#Post()
#Roles('user')
#UsePipes(new ValidationPipe())
#HttpCode(201)
#ApiResponse({ status: 201, description: 'The token has been successfully created.'})
#ApiResponse({ status: 403, description: 'Forbidden.'})
async createToken(#Body() createTokenDto: CreateTokenDto) {
this.tokenBuilderService.createToken(createTokenDto);
}
I'm looking into putting a REST layer (using Express) on top of a GraphQL server (Apollo Server v2) to support some legacy apps. To share as much logic as possible, the REST endpoint should ideally wrap a GraphQL query that I'm sending to the GraphQL server, and be able to do small modifications to the response before sending the response to the client.
I'm having trouble figuring out the best way to query the apollo server from the Express routing middleware. So far I've explored two different solutions:
Modify the request from the REST endpoint such that req.body is a valid graphql query, change the req.url to /graphql, and call next(). The problem with this is that I cannot modify the result before it's being sent to the client, which I need to do.
Calling the /graphql endpoint with axios from the routing middleware, and modify the response before sending to the client. This works, but feels to me a bit hacky.
Do you have other suggestions, or maybe even an example?
I believe the solution 2 is okay to implement.
I've made a similar implementation, but in my case, a GraphQL service fetches data from another(multiple) GraphQL service(s).
And somewhere down the line I did something like this:
export type serviceConnectionType = {
endpoint: string
queryType: {
query: Object // gql Object Query
variables: {
input: Object // query arguments (can be null)
}
}
}
export async function connectService(params: serviceConnectionType) {
const response = await fetch(params.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params.queryType),
})
if (response.status === 404) {
console.warn('404 not found')
}
return response.json()
}