View a markdown version of this page

处理 API Gateway 中的 Lambda 错误 - Amazon API Gateway

处理 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 函数必须在 "X-Amzn-ErrorType":"InvalidParameterException" 属性中包括标头(例如 headers)。

处理 API Gateway 中的标准 Lambda 错误

标准的 AWS 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 函数,该函数会引发具有相同 Exception 错误消息的 Malformed input ...。

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 ..." }

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

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

注意

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

例如,使用以下 put-integration-response 命令设置新 selectionPattern 表达式:

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 错误的 errorMessage 与 selectionPattern 属性的正则表达式模式相匹配。当存在匹配时,API Gateway 将返回 Lambda 错误作为相应 HTTP 状态码的 HTTP 响应。如果没有匹配,API Gateway 将返回错误作为默认响应,或者引发配置无效异常(如果未配置默认响应)。

针对给定响应数量,将 selectionPattern 值设置为 .* 会将此响应重置为默认响应。这是因为此类选择模式将匹配所有错误消息,包括 null (即,任何未指定的错误消息)。生成的映射会覆盖默认映射。如果您使用 .+ 作为选择模式来筛选响应,请注意,它可能与包含换行符('\n)的响应不匹配。

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

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

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

AWS 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.errorType、errorMessage.httpStatus、errorMessage.trace.function 和 errorMessage.trace 属性分别到 error_type、error_status、error_trace_function 和 error_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_status、error_trace、error_trace_function 和 error_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 标头。