

# 针对 API Gateway 中的 REST API 的 Lambda 集成
<a name="set-up-lambda-integrations"></a>

 您可以使用 Lambda 代理集成或 Lambda 非代理（自定义）集成将 API 方法与 Lambda 函数集成。

在 Lambda 代理集成中，所需的设置非常简单。将集成的 HTTP 方法设置为 POST，将集成端点 URI 指向特定 Lambda 函数的 Lambda 函数调用操作的 ARN，并授予 API Gateway 代表您调用 Lambda 函数的权限。

在 Lambda 非代理集成中，除了执行代理集成设置步骤，您还需要指定如何将传入请求数据映射到集成请求以及如何将生成的集成响应数据映射到方法响应。

**Topics**
+ [API Gateway 中的 Lambda 代理集成](set-up-lambda-proxy-integrations.md)
+ [在 API Gateway 中设置 Lambda 自定义集成](set-up-lambda-custom-integrations.md)
+ [设置后端 Lambda 函数的异步调用](set-up-lambda-integration-async.md)
+ [处理 API Gateway 中的 Lambda 错误](handle-errors-in-lambda-integration.md)

# API Gateway 中的 Lambda 代理集成
<a name="set-up-lambda-proxy-integrations"></a>

以下部分介绍如何使用 Lambda 代理集成。

**Topics**
+ [了解 API Gateway Lambda 代理集成](#api-gateway-create-api-as-simple-proxy)
+ [支持多值标头和查询字符串参数](#apigateway-multivalue-headers-and-parameters)
+ [用于代理集成的 Lambda 函数的输入格式](#api-gateway-simple-proxy-for-lambda-input-format)
+ [用于代理集成的 Lambda 函数的输出格式](#api-gateway-simple-proxy-for-lambda-output-format)
+ [使用 AWS CLI 为 API Gateway 设置 Lambda 代理集成](set-up-lambda-proxy-integration-using-cli.md)
+ [使用 OpenAPI 定义设置具有 Lambda 代理集成的代理资源](api-gateway-set-up-lambda-proxy-integration-on-proxy-resource.md)

## 了解 API Gateway Lambda 代理集成
<a name="api-gateway-create-api-as-simple-proxy"></a>

Amazon API Gateway Lambda 代理集成是通过设置单个 API 方法来构建 API 的简单、强大且灵活的机制。Lambda 代理集成允许客户端调用后端的单个 Lambda 函数。该函数可访问其他AWS服务的许多资源或功能，包括调用其他 Lambda 函数。

 在 Lambda 代理集成中，当客户端提交 API 请求时，API Gateway 将[事件对象](#api-gateway-simple-proxy-for-lambda-input-format)传递给集成的 Lambda 函数，但不会保留请求参数的顺序。此[请求数据](#api-gateway-simple-proxy-for-lambda-input-format)包括请求标头、查询字符串参数、URL 路径变量、负载和 API 配置数据。配置数据可以包括当前部署阶段名称、阶段变量、用户身份或授权上下文（如果有）。后端 Lambda 函数会对传入请求数据进行解析，以确定要返回的响应。要使 API Gateway 将 Lambda 输出作为 API 响应传递给客户端，Lambda 函数必须返回[此格式](#api-gateway-simple-proxy-for-lambda-output-format)的结果。

 因为 API Gateway 不过多地在 Lambda 代理集成的客户端和后端 Lambda 函数之间进行干预，所以客户端和集成的 Lambda 函数可以适应彼此的变化而不破坏 API 的现有集成设置。要实现这一点，客户端必须遵循后端 Lambda 函数所制定的应用程序协议。

 您可以为任何 API 方法设置 Lambda 代理集成。但是，当为涉及通用代理资源的 API 方法配置 Lambda 代理集成时，该集成更加有效。通用代理资源可由 `{proxy+}` 的特殊模板化路径变量和/或“捕获全部”`ANY` 方法占位符表示。客户端可以在传入请求中将输入作为请求参数或适用负载传递给后端 Lambda 函数。请求参数包括标头、URL 路径变量、查询字符串参数和适用负载。集成的 Lambda 函数会在处理请求之前验证所有输入源，如果缺少任何必需的输入，则会使用有意义的错误消息向客户端做出响应。

 在调用与通用 HTTP 方法 `ANY` 和通用资源 `{proxy+}` 集成的 API 方法时，客户端会使用特定 HTTP 方法而非 `ANY` 来提交请求。客户端还指定特定 URL 路径而非 `{proxy+}`，并包含任何所需的标头、查询字符串参数或适用负载。

 以下列表总结了使用 Lambda 代理集成的不同 API 方法的运行时行为：
+ `ANY /{proxy+}`：客户端必须选择特定 HTTP 方法，必须设置特定资源路径层次结构，并可以设置任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+ `ANY /res`：客户端必须选择特定 HTTP 方法，并可以设置任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+ `GET|POST|PUT|... /{proxy+}`：客户端可以设置特定资源路径层次结构、任何标头、查询字符串参数和适用负载以将数据作为输入传递给集成的 Lambda 函数。
+  `GET|POST|PUT|... /res/{path}/...`：客户端必须选择特定路径分段（针对 `{path}` 变量），并可以设置任何请求标头、查询字符串参数和适用负载以将输入数据传递给集成的 Lambda 函数。
+  `GET|POST|PUT|... /res`：客户端可以选择任何请求标头、查询字符串参数和适用负载以将输入数据传递给集成的 Lambda 函数。

 代理资源 `{proxy+}` 和自定义资源 `{custom}` 都表示为模板化路径变量。但是 `{proxy+}` 可以指路径层次结构中的任何资源，而 `{custom}` 只能指特定路径分段。例如，一个杂货店可以按品类名称、农产品类别和产品类型整理其上线产品库存。然后，该杂货店的网站可以通过自定义资源的以下模板化路径变量来表示可用产品：`/{department}/{produce-category}/{product-type}`。例如，通过 `/produce/fruit/apple` 来表示苹果，通过 `/produce/vegetables/carrot` 来表示胡萝卜。它还可以使用 `/{proxy+}` 来表示客户在其在线商店中购物时可以搜索的任何品类、任何农产品类别或任何产品类型。例如，`/{proxy+}` 可以指以下任一项：
+ `/produce`
+ `/produce/fruit`
+ `/produce/vegetables/carrot`

 要让客户搜索任何可用产品、其农产品类别和关联的商店品类，您可以公开具有只读权限的单个方法 `GET /{proxy+}`。同样地，要允许主管更新 `produce` 品类的库存，您可以设置另一个具有读/写权限的单个方法 `PUT /produce/{proxy+}`。要允许出纳员更新蔬菜的流水式总计，您可以设置一个具有读/写权限的 `POST /produce/vegetables/{proxy+}` 方法。要让商店经理对任何可用产品执行任何可能的操作，在线商店开发人员可以公开具有读/写权限的 `ANY /{proxy+}` 方法。任何情况下，在运行时，客户或员工都必须选择所选品类中给定类型的特定产品、所选品类中的特定农产品类别或特定品类。



有关设置 API Gateway 代理集成的更多信息，请参阅 [设置具有代理资源的代理集成](api-gateway-set-up-simple-proxy.md)。

 代理集成要求客户端更详细地了解后端要求。因此，要确保最佳的应用程序性能和用户体验，后端开发人员必须清楚地向客户端开发人员表明后端的要求，并在不符合要求时提供可靠的错误反馈机制。

## 支持多值标头和查询字符串参数
<a name="apigateway-multivalue-headers-and-parameters"></a>

API Gateway 支持多个具有相同名称的标头和查询字符串参数。多值标头以及单值标头和参数可以组合使用相同的请求和响应。有关更多信息，请参阅 [用于代理集成的 Lambda 函数的输入格式](#api-gateway-simple-proxy-for-lambda-input-format) 和 [用于代理集成的 Lambda 函数的输出格式](#api-gateway-simple-proxy-for-lambda-output-format)。

## 用于代理集成的 Lambda 函数的输入格式
<a name="api-gateway-simple-proxy-for-lambda-input-format"></a>

使用 Lambda 代理集成，API Gateway 可以将整个客户端请求映射到后端 Lambda 函数的输入 `event` 参数：以下示例显示了 API Gateway 发送到 Lambda 代理集成的事件的结构。

在本例中，我们假设对 API Gateway 的调用为以下内容：

```
curl 'https://a1b2c3.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter2=value1&parameter2=value2&parameter3=value1,value2' -H 'header1: value1' -H 'header2: value1' -H 'header2: value2' -H 'header3: value1,value2'
```

输出内容如下所示：

```
{
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
      "header1": "value1",
      "header2": "value2",
      "header3": "value1,value2"
  },
  "multiValueHeaders": {
    "header1": ["value1"],
    "header2": ["value1","value2"],
    "header3": ["value1,value2"]
  },
  "queryStringParameters": {
      "parameter1": "value1",
      "parameter2": "value2",
      "parameter3": "value1,value2"
  },
  "multiValueQueryStringParameters": {
    "parameter1": ["value1"],
    "parameter2": ["value1","value2"],
    "parameter3": ["value1,value2"]
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "id",
    "authorizer": {
      "claims": null,
      "scopes": null
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "extendedRequestId": "request-id",
    "httpMethod": "GET",
    "identity": {
      "accessKey": null,
      "accountId": null,
      "caller": null,
      "cognitoAuthenticationProvider": null,
      "cognitoAuthenticationType": null,
      "cognitoIdentityId": null,
      "cognitoIdentityPoolId": null,
      "principalOrgId": null,
      "sourceIp": "IP",
      "user": null,
      "userAgent": "user-agent",
      "userArn": null,
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "path": "/my/path",
    "protocol": "HTTP/1.1",
    "requestId": "id=",
    "requestTime": "04/Mar/2020:19:15:17 +0000",
    "requestTimeEpoch": 1583349317135,
    "resourceId": null,
    "resourcePath": "/my/path",
    "stage": "$default"
  },
  "pathParameters": null,
  "stageVariables": null,
  "body": "Hello from Lambda!",
  "isBase64Encoded": false
}
```

**注意**  
在输入中：  
`headers` 密钥只能包含单值标头。
`multiValueHeaders` 密钥可以包含多值标头以及单值标头。
如果您指定 `headers` 和 `multiValueHeaders` 的值，API Gateway 会将它们合并为一个列表。如果两者都指定了相同的键/值对，则合并列表中只会出现 `multiValueHeaders` 的值。

在后端 Lambda 函数的输入中，`requestContext` 对象是键/值对的映射。在每对中，键为 [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) 变量属性的名称，值为该属性的值。API Gateway 可能会向映射中添加新键。

根据启用的功能，不同 API 的 `requestContext` 映射可能有所不同。例如，在上述示例中，未指定任何授权类型，因此不存在任何 `$context.authorizer.*` 或 `$context.identity.*` 属性。当指定某个授权类型时，这会导致 API Gateway 将授权用户信息传递给 `requestContext.identity` 对象中的集成端点，如下所示：
+ 当授权类型为 `AWS_IAM` 时，授权用户信息包括 `$context.identity.*` 属性。
+ 当授权类型为 `COGNITO_USER_POOLS`（Amazon Cognito 授权方）时，授权用户信息包括 `$context.identity.cognito*` 和 `$context.authorizer.claims.*`。
+ 当授权类型为 `CUSTOM`（Lambda 授权方）时，授权用户信息包括 `$context.authorizer.principalId` 及其他适用的 `$context.authorizer.*` 属性。

## 用于代理集成的 Lambda 函数的输出格式
<a name="api-gateway-simple-proxy-for-lambda-output-format"></a>

在 Lambda 代理集成中，API Gateway 需要后端 Lambda 函数根据以下 JSON 格式返回输出：

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
```

在输出中：
+ 如果不返回任何额外的响应标头，则可以不指定 `headers` 和 `multiValueHeaders` 键。
+ `headers` 密钥只能包含单值标头。
+ `multiValueHeaders` 密钥可以包含多值标头以及单值标头。您可以使用 `multiValueHeaders` 密钥来指定所有额外的标头，包括任何单值标头。
+ 如果您指定 `headers` 和 `multiValueHeaders` 的值，API Gateway 会将它们合并为一个列表。如果两者都指定了相同的键/值对，则合并列表中只会出现 `multiValueHeaders` 的值。

要为 Lambda 代理集成启用 CORS，您必须将 `Access-Control-Allow-Origin:domain-name` 添加到输出 `headers`。`domain-name` 可以为 `*`，表示任意域名。输出 `body` 作为方法响应负载封送到前端。如果 `body` 是二进制 blob，您可以通过将 `isBase64Encoded` 设置为 `true` 并将 `*/*` 配置为**二进制媒体类型**来将其编码为采用 Base64 编码的字符串。否则，您可以将其设置为 `false` 或不进行指定。

**注意**  
有关启用二进制文件支持的更多信息，请参阅[使用 API Gateway 控制台启用二进制支持](api-gateway-payload-encodings-configure-with-console.md)。有关示例 Lambda 函数，请参阅 [从 API Gateway 中的 Lambda 代理集成返回二进制媒体](lambda-proxy-binary-media.md)。

如果函数输出属于其他格式，则 API Gateway 将返回 `502 Bad Gateway` 错误响应。

要在 Node.js 的 Lambda 函数中返回响应，您可以使用如下所示的命令：
+ 要返回成功的结果，请调用 `callback(null, {"statusCode": 200, "body": "results"})`。
+ 要引发异常，请调用 `callback(new Error('internal server error'))`。
+ 对于客户端错误（例如，如果缺少必需参数），可以调用 `callback(null, {"statusCode": 400, "body": "Missing parameters of ..."})` 以返回错误而不引发异常。

在 Node.js 的 Lambda `async` 函数中，等效的语法为：
+ 要返回成功的结果，请调用 `return {"statusCode": 200, "body": "results"}`。
+ 要引发异常，请调用 `throw new Error("internal server error")`。
+ 对于客户端错误（例如，如果缺少必需参数），可以调用 `return {"statusCode": 400, "body": "Missing parameters of ..."}` 以返回错误而不引发异常。

# 使用 AWS CLI 为 API Gateway 设置 Lambda 代理集成
<a name="set-up-lambda-proxy-integration-using-cli"></a>

在此部分中，我们将介绍如何使用 AWS CLI 设置 API 与 Lambda 代理集成。有关使用 API Gateway 控制台配置与 Lambda 代理集成的代理资源的详细说明，请参阅 [教程：利用 Lambda 代理集成创建 REST API](api-gateway-create-api-as-simple-proxy-for-lambda.md)。

例如，我们使用以下示例 Lambda 函数作为 API 的后端：

```
export const handler = async(event, context) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    var res ={
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    };
    var greeter = 'World';
    if (event.greeter && event.greeter!=="") {
        greeter =  event.greeter;
    } else if (event.body && event.body !== "") {
        var body = JSON.parse(event.body);
        if (body.greeter && body.greeter !== "") {
            greeter = body.greeter;
        }
    } else if (event.queryStringParameters && event.queryStringParameters.greeter && event.queryStringParameters.greeter !== "") {
        greeter = event.queryStringParameters.greeter;
    } else if (event.multiValueHeaders && event.multiValueHeaders.greeter && event.multiValueHeaders.greeter != "") {
        greeter = event.multiValueHeaders.greeter.join(" and ");
    } else if (event.headers && event.headers.greeter && event.headers.greeter != "") {
        greeter = event.headers.greeter;
    } 
    res.body = "Hello, " + greeter + "!";
    return res
};
```

将这一点与[在 API Gateway 中设置 Lambda 自定义集成](set-up-lambda-custom-integrations.md)中的 Lambda 自定义集成设置对比，对此 Lambda 函数的输入可能出现在请求参数和正文中。您可以有更多的自主度来允许客户端传递相同的输入数据。在这里，客户端可以将欢迎者的姓名作为查询字符串参数、标题或正文属性传递。该函数还支持 Lambda 自定义集成。API 设置更简单。您完全无需配置方法响应或集成响应。

**使用 AWS CLI 设置 Lambda 代理集成**

1. 使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建 API：

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   输出将与以下内容类似：

   ```
   {
       "name": "HelloWorldProxy (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   在本示例中，您使用了 API `id`（`te6si5ach7`）和 `rootResourceId`（`krznpq9xpg`）。

1. 使用以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令创建 `/greeting` 的 API Gateway [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)：

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part {proxy+}
   ```

   输出将与以下内容类似：

   ```
   {
       "path": "/{proxy+}", 
       "pathPart": "{proxy+}", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   在下一步中，您可以使用 `{proxy+}` 资源的 `id` 值（`2jf6xt`），在 `/{proxy+}` 资源上创建方法。

1. 使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 创建 `ANY /{proxy+}` 的 `ANY` 方法请求：

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method ANY \
          --authorization-type "NONE"
   ```

   输出将与以下内容类似：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "ANY", 
       "authorizationType": "NONE"
   }
   ```

   此 API 方法允许客户端从后端的 Lambda 函数接收或发送问候语。

1. 使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，设置 `ANY /{proxy+}` 方法与名为 `HelloWorld` 的 Lambda 函数的集成。在提供 `greeter` 参数时，此函数使用消息 `"Hello, {name}!"` 响应请求，在未设置查询字符串参数时使用 `"Hello, World!"` 响应。

   ```
   aws apigateway put-integration \
         --rest-api-id te6si5ach7 \
         --resource-id 2jf6xt \
         --http-method ANY \
         --type AWS_PROXY \
         --integration-http-method POST \
         --uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:HelloWorld/invocations \
         --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```
**重要**  
对于 Lambda 集成，根据[函数调用的 Lambda 服务操作规范](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)，您必须为集成请求使用 HTTP 方法 `POST`。`apigAwsProxyRole` 的 IAM 角色必须具有策略，允许 `apigateway` 服务调用 Lambda 函数。有关 IAM 权限的更多信息，请参阅[用于调用 API 的 API Gateway 权限模型](permissions.md#api-gateway-control-access-iam-permissions-model-for-calling-api)。

   输出将与以下内容类似：

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:1234567890:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "cacheNamespace": "vvom7n", 
       "credentials": "arn:aws:iam::1234567890:role/apigAwsProxyRole", 
       "type": "AWS_PROXY"
   }
   ```

   您不用为 `credentials` 提供 IAM 角色，而是可以使用 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令添加基于资源的权限。这是 API Gateway 控制台的功能。

1. 使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令，将 API 部署到 `test` 阶段：

   ```
   aws apigateway create-deployment  \
         --rest-api-id te6si5ach7 \
         --stage-name test
   ```

1. 在终端中使用以下 cURL 命令测试 API。

   使用查询字符串参数 `?greeter=jane` 调用 API：

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=jane'
   ```

   使用 `greeter:jane` 的标头参数调用 API：

   ```
   curl -X GET https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -H 'greeter: jane'
   ```

   使用 `{"greeter":"jane"}` 的正文调用 API：

   ```
   curl -X POST https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -d '{ "greeter": "jane" }'
   ```

   在所有情况下，输出为具有以下响应正文的 200 响应：

   ```
   Hello, jane!
   ```

# 使用 OpenAPI 定义设置具有 Lambda 代理集成的代理资源
<a name="api-gateway-set-up-lambda-proxy-integration-on-proxy-resource"></a>

要设置具有 Lambda 代理集成类型的代理资源，请创建一个具有“贪婪”路径参数（例如，`/parent/{proxy+}`）的 API 资源，并将该资源与 `arn:aws:lambda:us-west-2:123456789012:function:SimpleLambda4ProxyResource` 方法上的 Lambda 函数后端（例如，`ANY`）集成。“贪婪”路径参数必须位于 API 资源路径的末尾。与处理非代理资源一样，您可以通过使用 API Gateway 控制台、导入 OpenAPI 定义文件或直接调用 API Gateway REST API 来设置代理资源。

以下 OpenAPI API 定义文件显示了一个 API 的示例，该 API 具有与名为 `SimpleLambda4ProxyResource` 的 Lambda 函数集成的代理资源。

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T17:50:37Z",
      "title": "ProxyIntegrationWithLambda"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "POST",
               "cacheNamespace": "roq9wj",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "aws_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://gy415nuibc.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/testStage"
            }
         }
      }
   ]
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T17:50:37Z",
    "title": "ProxyIntegrationWithLambda"
  },
  "host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
  "basePath": "/testStage",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "cacheNamespace": "roq9wj",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "aws_proxy"
        }
      }
    }
  }
}
```

------

在 Lambda 代理集成中，在运行时，API Gateway 将传入请求映射到 Lambda 函数的输入 `event` 参数中。该输入包含请求方法、路径、标头、任何字符串参数、任何负载、关联的上下文以及定义的任何阶段变量。输入格式在[用于代理集成的 Lambda 函数的输入格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format)中说明。为了让 API Gateway 将 Lambda 输出成功映射到 HTTP 响应，Lambda 函数必须按照[用于代理集成的 Lambda 函数的输出格式](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format)中说明的格式输出结果。

在通过 `ANY` 方法实现代理资源的 Lambda 代理集成的过程中，单个后端 Lambda 函数充当通过代理资源的所有请求的事件处理程序。例如，要记录流量模式，您可以让移动设备提交一个代理资源的 URL 路径中附带 `/state/city/street/house` 的请求，从而发送包含州、城市、街道和建筑信息的位置信息。然后，后端 Lambda 函数可以分析 URL 路径并将位置元组插入 DynamoDB 表。

# 在 API Gateway 中设置 Lambda 自定义集成
<a name="set-up-lambda-custom-integrations"></a>

 为了显示如何设置 Lambda 自定义或非代理集成，我们创建了一个 API Gateway API，用于公开 `GET /greeting?greeter={name}` 方法来调用 Lambda 函数。为您的 API 使用以下 Lambda 函数示例之一。

使用以下 Lambda 函数示例之一：

------
#### [ Node.js ]

```
'use strict';
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];            
var times = ['morning', 'afternoon', 'evening', 'night', 'day'];

export const handler = async(event) => {
  console.log(event);
  // Parse the input for the name, city, time and day property values
  let name = event.name === null || event.name === undefined || event.name === "" ? 'you' : event.name;
  let city = event.city === undefined ? 'World' : event.city;
  let time = times.indexOf(event.time)<0 ? 'day' : event.time;
  let day = days.indexOf(event.day)<0 ? null : event.day;

  // Generate a greeting
  let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. ';
  if (day) greeting += 'Happy ' + day + '!';
  
  // Log the greeting to CloudWatch
  console.log('Hello: ', greeting);
  
  // Return a greeting to the caller
  return greeting;
};
```

------
#### [ Python ]

```
import json


def lambda_handler(event, context):
    print(event)
    res = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    }

    if event['greeter'] == "":
        res['body'] = "Hello, World"
    elif (event['greeter']):
        res['body'] = "Hello, " + event['greeter'] + "!"
    else:
        raise Exception('Missing the required greeter parameter.')

    return res
```

------

在 `greeter` 参数值为非空字符串时，该函数使用消息 `"Hello, {name}!"` 进行响应。如果 `greeter` 值是空字符串，则返回消息 `"Hello, World!"`。如果传入请求中未设置 greeter 参数，则返回错误消息 `"Missing the required greeter parameter."`。我们将函数命名为 `HelloWorld`。

您可以在 Lambda 控制台中或使用 AWS CLI 创建它。在此部分中，我们使用以下 ARN 引用此函数：

```
arn:aws:lambda:us-east-1:123456789012:function:HelloWorld
```

在后端设置了 Lambda 函数之后，继续设置 API。<a name="set-up-lambda-custom-integration-using-cli"></a>

**使用 AWS CLI 设置 Lambda 自定义集成**

1. 使用以下 [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) 命令创建 API：

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   输出将与以下内容类似：

   ```
   {
       "name": "HelloWorld (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   在本示例中，您使用了 API `id`（`te6si5ach7`）和 `rootResourceId`（`krznpq9xpg`）。

1. 使用以下 [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) 命令创建 `/greeting` 的 API Gateway [资源](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)：

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part greeting
   ```

   输出将与以下内容类似：

   ```
   {
       "path": "/greeting", 
       "pathPart": "greeting", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   在下一步中，您可以使用 `greeting` 资源的 `id` 值（`2jf6xt`），在 `/greeting` 资源上创建方法。

1. 使用以下 [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) 命令创建 `GET /greeting?greeter={name}` 的 API 方法请求：

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method GET \
          --authorization-type "NONE" \
          --request-parameters method.request.querystring.greeter=false
   ```

   输出将与以下内容类似：

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE", 
       "requestParameters": {
           "method.request.querystring.greeter": false
       }
   }
   ```

   此 API 方法允许客户端从后端的 Lambda 函数接收问候语。此 `greeter` 参数是可选的，因为后端应处理匿名调用方或自识别调用方。

1. 使用以下 [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) 命令，设置对 `GET /greeting?greeter={name}` 的方法请求的 `200 OK` 响应：

   ```
   aws apigateway put-method-response \
           --rest-api-id te6si5ach7 \ 
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200
   ```

   

1. 使用以下 [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) 命令，设置 `GET /greeting?greeter={name}` 方法与名为 `HelloWorld` 的 Lambda 函数的集成。在提供 `greeter` 参数时，函数使用消息 `"Hello, {name}!"` 响应请求，在未设置查询字符串参数时使用 `"Hello, World!"` 响应。

   ```
   aws apigateway put-integration \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --type AWS \
           --integration-http-method POST \
           --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations \
           --request-templates '{"application/json":"{\"greeter\":\"$input.params('greeter')\"}"}' \
           --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```

   此处提供的映射模板转换为 JSON 负载 `greeter` 属性的 `greeter` 查询字符串参数。这么做是必要的，因为对 Lambda 函数的输入必须在正文中表示。
**重要**  
对于 Lambda 集成，根据[函数调用的 Lambda 服务操作规范](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)，您必须为集成请求使用 HTTP 方法 `POST`。`uri` 参数是函数调用操作的 ARN。  
输出将与以下内容类似：

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "requestTemplates": {
           "application/json": "{\"greeter\":\"$input.params('greeter')\"}"
       }, 
       "cacheNamespace": "krznpq9xpg", 
       "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", 
       "type": "AWS"
   }
   ```

   `apigAwsProxyRole` 的 IAM 角色必须具有策略，允许 `apigateway` 服务调用 Lambda 函数。不同于为 `credentials` 提供 IAM 角色，您可以调用 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令以添加基于资源的权限。这就是 API Gateway 控制台添加这些权限的方式。

1. 使用以下 [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) 命令设置集成响应，用于将 Lambda 函数输出传递到客户端作为 `200 OK` 方法响应：

   ```
    aws apigateway put-integration-response \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200 \
           --selection-pattern ""
   ```

   将 selection-pattern 设置为空字符串时，`200 OK` 响应是默认值。

   输出将与以下内容类似：

   ```
    {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

1. 使用以下 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) 命令，将 API 部署到 `test` 阶段：

   ```
   aws apigateway create-deployment \
           --rest-api-id te6si5ach7 \
           --stage-name test
   ```

1.  在终端中使用以下 cURL 命令测试 API：

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=me' \
     -H 'authorization: AWS4-HMAC-SHA256 Credential={access_key}/20171020/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=f327...5751'
   ```

# 设置后端 Lambda 函数的异步调用
<a name="set-up-lambda-integration-async"></a>

在 Lambda 非代理（自定义）集成中，默认情况下后端 Lambda 函数是同步调用的。这是大多数 REST API 操作的预期行为。但是，某些应用程序通常需要由某个单独的后端组件进行异步执行（如分批操作或长延迟操作）才能运行。在这种情况下，后端 Lambda 函数将进行异步调用，而且前端 REST API 方法不会返回结果。

您可以通过将 `'Event'` 指定为 [Lambda 调用类型](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)，为要异步调用的 Lambda 非代理集成配置 Lambda 函数。按如下所示完成此操作：

## 在 API Gateway 控制台中配置 Lambda 异步调用
<a name="asynchronous-invocation-console-examples"></a>

要使所有调用均为异步，请执行以下操作：
+ 在**集成请求**中，添加使用静态值 `'Event'` 的 `X-Amz-Invocation-Type` 标头。

要让客户端决定调用为异步还是同步，请执行以下操作：

1. 在**方法请求**中，添加 `InvocationType` 标头。

1. 在**集成请求**中，添加使用映射表达式 `method.request.header.InvocationType` 的 `X-Amz-Invocation-Type` 标头。

1. 在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

## 使用 OpenAPI 配置 Lambda 异步调用
<a name="asynchronous-invocation-OpenAPI-examples"></a>

要使所有调用均为异步，请执行以下操作：
+  将 `X-Amz-Invocation-Type` 标头添加到 **x-amazon-apigateway-integration** 部分。

  ```
  "x-amazon-apigateway-integration" : {
            "type" : "aws",
            "httpMethod" : "POST",
            "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
            "responses" : {
              "default" : {
                "statusCode" : "200"
              }
            },
            "requestParameters" : {
              "integration.request.header.X-Amz-Invocation-Type" : "'Event'"
            },
            "passthroughBehavior" : "when_no_match",
            "contentHandling" : "CONVERT_TO_TEXT"
          }
  ```

要让客户端决定调用为异步还是同步，请执行以下操作：

1.  在任何 [OpenAPI 路径项对象](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject)上添加以下标头。

   ```
   "parameters" : [ {
   "name" : "InvocationType",
   "in" : "header",
   "schema" : {
     "type" : "string"
   }
   } ]
   ```

1.  将 `X-Amz-Invocation-Type` 标头添加到 **x-amazon-apigateway-integration** 部分。

   ```
   "x-amazon-apigateway-integration" : {
             "type" : "aws",
             "httpMethod" : "POST",
             "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
             "responses" : {
               "default" : {
                 "statusCode" : "200"
               }
             },
             "requestParameters" : {
               "integration.request.header.X-Amz-Invocation-Type" : "method.request.header.InvocationType"
             },
             "passthroughBehavior" : "when_no_match",
             "contentHandling" : "CONVERT_TO_TEXT"
           }
   ```

1.  在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

## 使用 CloudFormation 配置 Lambda 异步调用
<a name="asynchronous-invocation-cfn-examples"></a>

以下 CloudFormation 模板显示如何配置 `AWS::ApiGateway::Method` 来进行异步调用。

要使所有调用均为异步，请执行以下操作：

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: "'Event'"
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

要让客户端决定调用为异步还是同步，请执行以下操作：

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      RequestParameters:
        method.request.header.InvocationType: false
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: method.request.header.InvocationType
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

 在 API 请求中，对于异步调用，客户端可以包含 `InvocationType: Event` 标头，对于同步调用则可以包含 `InvocationType: RequestResponse`。

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