【问题标题】:What's the correct way of returning HTTP error codes in serverless lambda在无服务器 lambda 中返回 HTTP 错误代码的正确方法是什么
【发布时间】:2018-03-23 04:58:53
【问题描述】:

我有一个用 Node.JS 编写的无服务器 lambda 函数。

返回错误代码的最佳/正确方法是什么?

我现在使用的模式(并且有效!)是:

module.exports.endpoint = (event, context, callback) => {
    const response = {
        statusCode: 404,
        body: JSON.stringify({ message: 'Hello World!' })
    };
    callback(null, response);
}

当我拨打电话(例如从 POSTMAN 拨打电话)到我的端点时,我得到:

Status: 404 Not Found 正是我所期待的。

此外,在日志中我可以看到:

Serverless: GET / (λ: get)
Serverless: [404] {"statusCode":404,"body":"{\"message\":\"Hello World!\"}"}

效果很好。

困扰我的是我将null 作为错误传递。查看其他一些教程/示例,我发现了以下模式:

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

所有这些都非常有意义,您可以指定 HTTP 状态代码 - 但我最终得到的是 HTTP 状态代码 200。当我查看日志时,我可以看到错误紧跟在 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

在这个地方我找到了以下解释: https://github.com/serverless/serverless/issues/4119

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

下面的例子:

Sample 403:
callback(null, { statusCode: 403, body: "Forbidden", headers: { "Content-Type": "text/plain" } });
Sample 404:
callback(null, { statusCode: 400 });

所以这与我的方式基本相同。为了完整起见,我可以补充一点,还有很多使用 context.fail(result) 或 context.succeed(result) 的示例 - 但从我收集的内容来看,context 已被弃用,不应使用(即使它仍然有效) .

使用callback(error)有什么意义?

【问题讨论】:

    标签: node.js aws-lambda aws-api-gateway serverless-framework serverless


    【解决方案1】:

    如果您想在这种情况下响应 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 可以重试调用。

    【讨论】:

    • 我看到您最终使用了相同的方式:return callback(null, createResponse) - 将null 作为错误传递,然后实际错误进入结果。
    • 是的。正如我所说,您应该处理 API Gateway Lambda 的错误。
    • @iaforek 你还在纠结什么?
    • 我并不困惑。对错误的处理方式及其背后的文档有点失望。
    • @iaforek 这就是适合您的 AWS。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 2018-03-21
    • 2021-07-02
    • 2021-10-30
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多