处理 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 错误
标准的 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 函数,该函数会引发具有相同 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 ..." }
请注意,errorType
和 stackTrace
属性值因语言而异。标准错误也适用于作为 Error
对象的扩展或 Exception
类的子类的任何错误对象。
要将标准 Lambda 错误映射到方法响应,您必须首先为给定的 Lambda 错误确定 HTTP 状态代码。然后,针对与给定 HTTP 状态代码相关联的 IntegrationResponse 的 selectionPattern
属性设置正则表达式模式。在 API Gateway 控制台的集成响应部分,此 selectionPattern
在每个集成响应下方表示为 Lambda 错误正则表达式。
注意
API Gateway 使用 Java 模式的正则表达式来响应映射。有关更多信息,请参阅 Oracle 文档中的模式
例如,要设置新的 selectionPattern
表达式,请使用 AWS 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 错误的 errorMessage
与 selectionPattern
属性的正则表达式模式相匹配。当存在匹配时,API Gateway 将返回 Lambda 错误作为相应 HTTP 状态码的 HTTP 响应。如果没有匹配,API Gateway 将返回错误作为默认响应,或者引发配置无效异常(如果未配置默认响应)。
针对给定响应数量,将 selectionPattern
值设置为 .*
会将此响应重置为默认响应。这是因为此类选择模式将匹配所有错误消息,包括 null (即,任何未指定的错误消息)。生成的映射会覆盖默认映射。
要使用 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
标头。