问题
I have a serverless lambda function written in Node.JS.
What is the best / correct way of returning error codes?
The pattern that I use right now (and it works!) is:
module.exports.endpoint = (event, context, callback) => {
const response = {
statusCode: 404,
body: JSON.stringify({ message: 'Hello World!' })
};
callback(null, response);
}
When I make a call, for example from POSTMAN, to my endpoint I get:
Status: 404 Not Found
which is exactly what I'm expecting.
Moreover, in the logs I can see:
Serverless: GET / (λ: get)
Serverless: [404] {"statusCode":404,"body":"{\"message\":\"Hello World!\"}"}
That works well.
What bothers me is that I'm passing null
as the error. Looking into a few other tutorials/examples I've found patterns like:
https://aws.amazon.com/blogs/compute/error-handling-patterns-in-amazon-api-gateway-and-aws-lambda/
https://serverless.com/framework/docs/providers/aws/events/apigateway/
callback ("the sky is falling!");
callback("[BadRequest] Validation error: Missing field 'name'");
callback("[404] Not Found");
callback(new Error('[404] Not found'));
callback(JSON.stringify(myErrorObj));
All of them make perfect sense and you can specify HTTP Status Code - yet what I'm getting is HTTP Status Code 200 in the end. When I look at the logs I can see that the error was followed straight after with 200:
Serverless: GET / (λ: get)
Serverless: Failure: the sky is falling!
Serverless: Replying 200
Serverless: GET / (λ: get)
Serverless: Failure: [BadRequest] Validation error: Missing field 'name'
Serverless: Replying 200
Serverless: GET / (λ: get)
Serverless: Failure: [404] Not Found
Serverless: Replying 200
Serverless: GET / (λ: get)
Serverless: Failure: [404] Not found
Serverless: Replying 200
Serverless: GET / (λ: get)
Serverless: Failure: {"errorType":"InternalServerError","httpStatus":500,"message":"An unknown error has occurred. Please try again."}
Serverless: Replying 200
In this place I've found following explanation: https://github.com/serverless/serverless/issues/4119
If you want to respond with HTTP errors in that case, you have to encode the HTTP error as successful Lambda response
with following example:
Sample 403:
callback(null, { statusCode: 403, body: "Forbidden", headers: { "Content-Type": "text/plain" } });
Sample 404:
callback(null, { statusCode: 400 });
So that's basically the same way I've. For the sake of completeness, I can add that there is also a plenty of examples that uses context.fail(result)
or context.succeed(result)
- but from what I gathered context
is deprecated and shouldn't be used (even though it still works).
What is the point of using callback(error)
?
回答1:
If you want to respond with HTTP errors in that case, you have to encode the HTTP error as successful Lambda response
This way of error-handling is specific to API Gateway.
Just like in traditional Node web servers (e.g. express), you can throw any error using `throw new Error('Invalid Payload') and a middleware usually converts it into an HTTP response with the correct response status.
In API Gateway Lambda, this can be written like this...
function createResponse(status, body) {
return {
headers: {
'Access-Control-Allow-Origin': '*',
}
statusCode: status,
body: JSON.stringify(body)
}
}
module.exports.endpoint = (event, context, callback) => {
try {
return callback(null, createResponse(200, processEvent(event)))
} except (e)
console.error(e)
return callback(null, createResponse(500, {
error: 'Internal Server Error',
}))
}
Basically, it's a handled error. The lambda function succeeded but the request failed (maybe 400, 404, or 500).
You should be handling errors always, or else if your handler crashes (due to a runtime error or syntax error or any unhandler error), your user will get an unexpected response (a 500 or a 502) which you probably don't want.
That being said, please remember that Lambda is not only used for API Gateway. callback(error)
is used for non-API Gateway-triggered Lambdas.
For example, if you have an SNS-triggered Lambda, you can return callback('Any error message here')
and it will let SNS know that it failed and so SNS can retry the invocation.
来源:https://stackoverflow.com/questions/46689554/whats-the-correct-way-of-returning-http-error-codes-in-serverless-lambda