【问题标题】:API Gateway Mock Integration Fails with 500API Gateway 模拟集成失败并显示 500
【发布时间】:2017-10-14 21:16:14
【问题描述】:

我有一个用于方法/资源的 API 网关集成,当我从 API 调用它时有效,但在我实际调用它时无效:

$ aws apigateway test-invoke-method --rest-api-id $REST_API_ID \
    --resource-id $RESOURCE_ID --http-method GET | jq -r .log,.body

这很好,我得到以下输出:

Tue May 16 17:46:42 UTC 2017 : Starting execution for request: test-invoke-request
Tue May 16 17:46:42 UTC 2017 : HTTP Method: GET, Resource Path: /status.json
Tue May 16 17:46:42 UTC 2017 : Method request path: {}
Tue May 16 17:46:42 UTC 2017 : Method request query string: {}
Tue May 16 17:46:42 UTC 2017 : Method request headers: {}
Tue May 16 17:46:42 UTC 2017 : Method request body before transformations:
Tue May 16 17:46:42 UTC 2017 : Endpoint response body before transformations:
Tue May 16 17:46:42 UTC 2017 : Endpoint response headers: {}
Tue May 16 17:46:42 UTC 2017 : Method response body after transformations: { "statusCode": 200 }
Tue May 16 17:46:42 UTC 2017 : Method response headers: {Content-Type=application/json}
Tue May 16 17:46:42 UTC 2017 : Successfully completed execution
Tue May 16 17:46:42 UTC 2017 : Method completed with status: 200

{ "statusCode": 200 }

但是,我无法通过我的 URL(api.naftuli.wtf/v1/status.json)访问它。我在glhfstablev1 定义了阶段,因此通过替换它,您将看到不同的响应。我只是想要一个返回 200 JSON blob 的虚拟响应。

我的资源 Terraform 是 here as a Gist。希望这能充分展示我的 API Gateway 配置。

如果我从 CLI 或 Web 控制台测试调用它,我会得到预期的结果。但是,如果我从我在 api.naftuli.wtf 部署的 API 中卷曲它,我不会得到任何好处:

$ for stage in glhf stable v1 ; do 
>   url="https://api.naftuli.wtf/${stage}/status.json"
>   echo "${url}:" 
>   curl -i -H 'Content-Type: application/json' \
>     https://api.naftuli.wtf/${stage}/status.json
>   echo -e '\n
> done
https://api.naftuli.wtf/glhf/status.json:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:38 GMT
x-amzn-RequestId: 712ba52b-3a80-11e7-9fec-b79b62d3bf7f
X-Cache: Error from cloudfront
Via: 1.1 da7a5d0ed7f424609000879e43743066.cloudfront.net (CloudFront)
X-Amz-Cf-Id: hBwlbPCP9n2rlz53I-Qb9KoffHB_FoxUCZUaJYNnU3XhCWuMpQTP1Q==

{"message": "Internal server error"}

https://api.naftuli.wtf/stable/status.json:
HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 23
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:38 GMT
x-amzn-RequestId: 71561066-3a80-11e7-9b00-6700be628328
x-amzn-ErrorType: ForbiddenException
X-Cache: Error from cloudfront
Via: 1.1 0c146399837c7d36c1f0f9d2636f8cf8.cloudfront.net (CloudFront)
X-Amz-Cf-Id: ITX765xD8s4sNuOdXaJ2kPvqPo-w_dsQK3Sq_No130FAHxFuoVhO8w==

{"message":"Forbidden"}

https://api.naftuli.wtf/v1/status.json:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:39 GMT
x-amzn-RequestId: 7185fa99-3a80-11e7-a3b1-2f9e659fc361
X-Cache: Error from cloudfront
Via: 1.1 586f1a150b4ba39f3a668b8055d4d5ea.cloudfront.net (CloudFront)
X-Amz-Cf-Id: dvnOa1s-YlwLSNzBfVyx5tSL6XrjFJM4_fES7MyTofykB3ReU5R1fg==

{"message": "Internal server error"}

我对阶段的理解是,它们是基本路径的附加路径前缀,所有 API 资源都在该路径下可用。如果我有一个名为v1 且路径为/v1 的阶段,我希望status.json 的API 网关资源将基本上映射到/v1 下,从而产生/v1/status.json

我可能误解了 API Gateway 基本路径映射和阶段的工作方式,但 CloudWatch 告诉我调用至少正在发生,尽管由于某些不明原因而失败:

21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Verifying Usage Plan for request: c5be3842-6af4-4725-a34f-d6eea8042d17. API Key: API Stage: tcips69qx2/prod_v1
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) API Key authorized because method 'GET /status.json' does not require API Key. Request will not contribute to throttle or quota limits
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Usage Plan check succeeded for API Key and API Stage tcips69qx2/prod_v1
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Starting execution for request: c5be3842-6af4-4725-a34f-d6eea8042d17
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) HTTP Method: GET, Resource Path: /v1/status.json
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Execution failed due to configuration error: statusCode should be an integer which defined in request template
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Method completed with status: 500

显然只有跨 V1 阶段的流量通过 CloudWatch 日志。我在某处配置错误,但似乎找不到。

【问题讨论】:

  • 听起来像是自定义域名设置中的基本路径映射有问题。如果您希望 api.naftuli.wtf/v1/status.json 使用阶段名称为 v1 的单个 API,那么您需要一个带有空基本路径和空阶段的基本路径映射(因为您指定它在调用路径中),并映射到您的 restApiId。
  • @MikeDatAWS 我已经更新了问题和provided a link to more of my Terraform
  • 嗨,Naftuli Kay。将其中一个答案标记为已接受的答案将是有用的文档。

标签: aws-api-gateway terraform


【解决方案1】:

您能否尝试将集成请求设置中的请求模板更改为:

{
  "statusCode": 200
}

API Gateway 会在您的 integration request template 的响应中查找要返回的状态代码。响应由集成响应中的映射模板生成。我可以从您的 terraform 设置中看到,您正在将输出 json 文件加载到集成请求模板中。这是 API Gateway 不期望的内容。

【讨论】:

  • 就我而言,我需要删除statusCode中的引用
  • { statusCode: 200 }
  • 谢谢你!这是我的问题,我使用云形成来部署我的 API,并且从未将集成请求映射模板添加到 OPTIONS 方法中!
  • 在集成请求中删除 statusCode 的引用也对我有用。这很奇怪,因为 "statusCode" 是在我使用 Mock Integration Endpoint 从头开始​​创建新 API 时自动填充的。
【解决方案2】:

您的配置至少有两个明显的问题。

首先,您的三个基本路径映射之一与您尝试调用 API 的方式不匹配。请注意,基本路径不必与您的舞台名称相同,但如果您愿意,它们可以是相同的。由于您的基本路径映射包括基本路径和阶段名称,API Gateway 期望调用路径包含基本路径映射而不是阶段,因此它将路径的 [glhf stable v1] 部分解释为基本路径并查找为相应的基本路径映射条目确定要使用的 API 和阶段。这适用于返回 500(表示不同的问题)的 v1 和 glhf 基本路径。稳定的基本路径(https://api.naftuli.wtf/stable/status.json)返回 403 Forbidden,因为没有为域名 api.naftuli.wtf 定义“稳定”的基本路径。稳定阶段映射到“最新”基本路径,因此调用https://api.naftuli.wtf/latest/status.json 应该是调用稳定阶段的方式。这目前不起作用,我不知道为什么。如果你告诉我你在哪个区域运行它,我可以查找配置并进行更多挖掘。

您的 CloudWatch 日志中的以下条目表明了第二个问题:

由于配置错误导致执行失败:statusCode应该是请求模板中定义的整数

您能否检查您的集成请求模板(在“${file("${path.module}/files/status.json")}”中您引用的文件中)是否包含“statusCode: 200”作为顶部等级属性。

我还发现您对请求模板和响应模板使用相同的文件感到惊讶。

【讨论】:

  • 嘿@mike-at-aws,来自AWS docs 的这个怎么样:“或者,您可以让模拟集成的方法返回默认集成响应而不定义集成请求映射模板”
【解决方案3】:

遇到相同的错误后,我发现帮助我解决此问题的方法是在 AWS 控制台中删除我的 OPTIONS 请求定义。然后我按照控制台的“启用 CORS”表单创建了一个新的 OPTIONS 方法。

我随后运行 terraform plan 并查看了我的 OPTIONS 定义和他们的定义之间的差异。鉴于 AWS 控制台创建的 OPTIONS 方法有效,我应用了更改。

使用 terraform 0.12 或更高版本可以实现这一点,因为 terraform plan 输出细节更加精细。

【讨论】:

    【解决方案4】:

    显然,这里特别奇怪的是,修复只是使用 AWS CLI 为每个阶段创建部署。显然,Terraform 没有根据更改更新或重新启动部署,因此我的更改从未发布。

    【讨论】:

      【解决方案5】:

      我在 CloudFormation 中执行此操作。

      我花了一段时间才得到它,这里接受的答案非常有帮助,但有点模糊,所以添加更多信息。

      Stefano Buliani 在 CloudFormation YAML 中的回答如下:

      RequestTemplates:
          application/json: | 
              { statusCode: 200 }
      

      【讨论】:

        【解决方案6】:

        使用模拟集成 Amazon API Gateway 有 2 个常见原因导致 500 Internal Server 错误。

        1. 检查集成请求中的映射模板,并确保将 statusCode 作为整数传递给 MOCK 集成端点。

          { “statusCode”: }

        注意:确保状态码以整数而不是字符串形式传递。

        正确:200 不正确:“200”

        1. 模拟集成不支持二进制内容。如果 API 启用了二进制支持并将 application/json 或 */* 设置为 binaryMediaTypes,则 MOCK 集成端点在尝试转换内容时会抛出 500 Internal server error。

          解决方法是将 MOCK 集成的 contentHandling 属性更新为 CONVERT_TO_TEXT

        在此处阅读更多信息:- https://cloudnamaste.com/500-internal-server-error-mock-integration/

        【讨论】:

          【解决方案7】:

          我遇到了类似的问题,最终发现我的客户使用的内容类型与我预期的不同。我曾经愚蠢地认为它会使用 application/json,但它是一些自定义的 json 东西。在我的设置中,API Gateway 正在登录到 cloudwatch,这是我发现它从客户端接收到的内容类型的地方。一旦我更新了模拟集成的请求模板中的内容类型,事情就按预期工作了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-12-03
            • 2018-10-29
            • 2022-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多