

# 处理 API Gateway 中的 Lambda 错误
<a name="handle-errors-in-lambda-integration"></a>

 对于 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`）。

**Topics**
+ [处理 API Gateway 中的标准 Lambda 错误](#handle-standard-errors-in-lambda-integration)
+ [处理 API Gateway 中的自定义 Lambda 错误](#handle-custom-errors-in-lambda-integration)

## 处理 API Gateway 中的标准 Lambda 错误
<a name="handle-standard-errors-in-lambda-integration"></a>

标准的 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](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) 的 `[selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern)` 属性设置正则表达式模式。在 API Gateway 控制台的**集成响应**部分，此 `selectionPattern` 在每个集成响应下方表示为 **Lambda 错误正则表达式**。

**注意**  
API Gateway 使用 Java 模式的正则表达式来响应映射。有关更多信息，请参阅 Oracle 文档中的[模式](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)。

 例如，使用以下 [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) 命令设置新 `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
```

 确保您还针对 [方法响应](api-gateway-method-settings-method-response.md#setup-method-response-status-code) 设置了相应的错误代码 (`400`)。否则，API Gateway 会在运行时引发一个关于配置无效的错误响应。

**注意**  
 在运行时，API Gateway 将 Lambda 错误的 `errorMessage` 与 `selectionPattern` 属性的正则表达式模式相匹配。当存在匹配时，API Gateway 将返回 Lambda 错误作为相应 HTTP 状态码的 HTTP 响应。如果没有匹配，API Gateway 将返回错误作为默认响应，或者引发配置无效异常（如果未配置默认响应）。  
 针对给定响应数量，将 `selectionPattern` 值设置为 `.*` 会将此响应重置为默认响应。这是因为此类选择模式将匹配所有错误消息，包括 null (即，任何未指定的错误消息)。生成的映射会覆盖默认映射。如果您使用 `.+` 作为选择模式来筛选响应，请注意，它可能与包含换行符（'`\n`）的响应不匹配。

 要使用 `selectionPattern` 更新现有 AWS CLI 值，请调用 [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) 操作，以将 `/selectionPattern` 路径值替换为 `Malformed*` 模式的指定正则表达式。



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

## 处理 API Gateway 中的自定义 Lambda 错误
<a name="handle-custom-errors-in-lambda-integration"></a>

 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` 标头。