处理 API Gateway 中的 Lambda 错误 - Amazon API Gateway
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

处理 API Gateway 中的 Lambda 错误

对于 Lambda 自定义集成,您必须将在集成响应中由 Lambda 返回的错误映射到客户端的标准 HTTP 错误响应。否则,Lambda 错误会默认返回为 200 OK 响应,并且结果对于您的 API 用户而言并不直观。

Lambda 可以返回两种类型的错误:标准错误和自定义错误。在您的 API 中,您必须以不同方式处理这些错误。

对于 Lambda 代理集成,Lambda 需要返回以下格式的输出:

{ "isBase64Encoded" : "boolean", "statusCode": "number", "headers": { ... }, "body": "JSON string" }

在此输出中,statusCode 通常为 4XX (对于客户端错误) 和 5XX (对于服务器错误)。API Gateway 可根据指定的 statusCode,通过将 Lambda 错误到 HTTP 错误响应来处理这些错误。要使 API Gateway 将错误类型(例如 InvalidParameterException)作为响应的一部分传递给客户端,Lambda 函数必须在 headers 属性中包括标头(例如 "X-Amzn-ErrorType":"InvalidParameterException")。

处理 API Gateway 中的标准 Lambda 错误

标准的 Amazon Lambda 错误具有以下格式:

{ "errorMessage": "<replaceable>string</replaceable>", "errorType": "<replaceable>string</replaceable>", "stackTrace": [ "<replaceable>string</replaceable>", ... ] }

其中,errorMessage 是错误的字符串表达式。errorType 是取决于语言的错误或异常类型。stackTrace 是一个字符串表达式列表,显示导致发生错误的堆栈跟踪。

例如,请考虑以下 JavaScript (Node.js) Lambda 函数。

export const handler = function(event, context, callback) { callback(new Error("Malformed input ...")); };

此函数返回以下标准 Lambda 错误,其中包含 Malformed input ... 作为错误消息:

{ "errorMessage": "Malformed input ...", "errorType": "Error", "stackTrace": [ "export const handler (/var/task/index.js:3:14)" ] }

同样,请考虑以下 Python Lambda 函数,该函数会引发具有相同 Malformed input ... 错误消息的 Exception

def lambda_handler(event, context): raise Exception('Malformed input ...')

此函数会返回以下标准 Lambda 错误:

{ "stackTrace": [ [ "/var/task/lambda_function.py", 3, "lambda_handler", "raise Exception('Malformed input ...')" ] ], "errorType": "Exception", "errorMessage": "Malformed input ..." }

请注意,errorTypestackTrace 属性值因语言而异。标准错误也适用于作为 Error 对象的扩展或 Exception 类的子类的任何错误对象。

要将标准 Lambda 错误映射到方法响应,您必须首先为给定的 Lambda 错误确定 HTTP 状态代码。然后,针对与给定 HTTP 状态代码相关联的 IntegrationResponseselectionPattern 属性设置正则表达式模式。在 API Gateway 控制台的集成响应部分,此 selectionPattern 在每个集成响应下方表示为 Lambda 错误正则表达式

注意

API Gateway 使用 Java 模式的正则表达式来响应映射。有关更多信息,请参阅 Oracle 文档中的模式

例如,要设置新的 selectionPattern 表达式,请使用 Amazon CLI 调用以下 put-integration-response 命令:

aws apigateway put-integration-response --rest-api-id z0vprf0mdh --resource-id x3o5ih --http-method GET --status-code 400 --selection-pattern "Malformed.*" --region us-west-2

确保您还针对 方法响应 设置了相应的错误代码 (400)。否则,API Gateway 会在运行时引发一个关于配置无效的错误响应。

注意

在运行时,API Gateway 将 Lambda 错误的 errorMessageselectionPattern 属性的正则表达式模式相匹配。当存在匹配时,API Gateway 将返回 Lambda 错误作为相应 HTTP 状态码的 HTTP 响应。如果没有匹配,API Gateway 将返回错误作为默认响应,或者引发配置无效异常(如果未配置默认响应)。

针对给定响应数量,将 selectionPattern 值设置为 .* 会将此响应重置为默认响应。这是因为此类选择模式将匹配所有错误消息,包括 null (即,任何未指定的错误消息)。生成的映射会覆盖默认映射。

要使用 selectionPattern 更新现有 Amazon CLI 值,请调用 update-integration-response 操作,以将 /selectionPattern 路径值替换为 Malformed* 模式的指定正则表达式。

要使用 API Gateway 控制台设置 selectionPattern 表达式,请在设置或更新指定 HTTP 状态代码的集成响应时,在 Lambda 错误正则表达式文本框中输入表达式。

处理 API Gateway 中的自定义 Lambda 错误

Amazon Lambda 允许您返回自定义错误对象作为 JSON 字符串,而不是返回上一部分所述的标准错误。该错误可以是任何有效的 JSON 对象。例如,下面的 JavaScript (Node.js) Lambda 函数会返回自定义错误:

export const handler = (event, context, callback) => { ... // Error caught here: var myErrorObj = { errorType : "InternalServerError", httpStatus : 500, requestId : context.awsRequestId, trace : { "function": "abc()", "line": 123, "file": "abc.js" } } callback(JSON.stringify(myErrorObj)); };

您必须先将 myErrorObj 对象转换为 JSON 字符串,然后才能调用 callback 以退出函数。否则,myErrorObj 会返回为 "[object Object]" 字符串。当您的 API 方法与上述 Lambda 函数集成时,API Gateway 会接收具有以下负载的集成响应:

{ "errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}" }

与任何集成响应一样,您可以将此错误响应按原样传递至方法响应。或者,您可以使用映射模板将负载转换为另一种格式。例如,针对 500 状态代码的方法响应考虑以下正文映射模板:

{ errorMessage: $input.path('$.errorMessage'); }

此模板会将包含自定义错误 JSON 字符串的集成响应正文转换为以下方法响应正文。此方法响应正文包含自定义错误 JSON 对象:

{ "errorMessage" : { errorType : "InternalServerError", httpStatus : 500, requestId : context.awsRequestId, trace : { "function": "abc()", "line": 123, "file": "abc.js" } } };

根据您的 API 要求,您可能需要传递部分或全部自定义错误属性作为方法响应标头参数。为实现这一点,您可以将来自集成响应正文的自定义错误映射应用到方法响应标头。

例如,下面的 OpenAPI 扩展定义了 errorMessage.errorTypeerrorMessage.httpStatuserrorMessage.trace.functionerrorMessage.trace 属性分别到 error_typeerror_statuserror_trace_functionerror_trace 标头的映射。

"x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200", "responseParameters": { "method.response.header.error_trace_function": "integration.response.body.errorMessage.trace.function", "method.response.header.error_status": "integration.response.body.errorMessage.httpStatus", "method.response.header.error_type": "integration.response.body.errorMessage.errorType", "method.response.header.error_trace": "integration.response.body.errorMessage.trace" }, ... } } }

在运行时,API Gateway 会在执行标头映射时反序列化 integration.response.body 参数。但是,这种反序列化仅适用于 Lambda 自定义错误响应的“正文到标头”映射,并不适用于使用 $input.body 的“正文到正文”映射。使用这些 custom-error-body-to-header 映射,客户端会收到以下标头作为方法响应的一部分,前提是方法请求中声明了 error_statuserror_traceerror_trace_functionerror_type 标头。

"error_status":"500", "error_trace":"{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}", "error_trace_function":"abc()", "error_type":"InternalServerError"

集成响应正文的 errorMessage.trace 属性是一个复杂的属性。它会作为 JSON 字符串映射到 error_trace 标头。