12

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)?

4

1 回答 1

9

如果您想在这种情况下响应 HTTP 错误,则必须将 HTTP 错误编码为成功的 Lambda 响应

这种类型的错误处理特定于 API Gateway。

就像在传统的 Node Web 服务器(例如 express)中一样,您可以抛出任何错误throw new Error('Invalid Payload'),并且中间件通常会将其转换为具有正确响应状态的 HTTP 响应。

在 API Gateway Lambda 中,可以这样写...

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'
      }))
}

基本上,这是一个已处理的错误。lambda 函数成功但请求失败(可能是 400、404 或 500)。

您应该始终处理错误,否则如果您的处理程序崩溃(由于运行时错误或语法错误或任何未处理的错误),您的用户将收到您可能不想要的意外响应(500 或 502)。


请记住,Lambda 不仅用于 API 网关。callback(error)用于非 API 网关触发的 Lambda。

例如,如果您有一个 SNS 触发的 Lambda,您可以返回callback('Any error message here'),它会让 SNS 知道它失败了,因此 SNS 可以重试调用。

于 2017-10-11T21:05:28.280 回答