API网关模拟集成失败,500

时间:2017-05-15 23:55:29

标签: aws-api-gateway terraform

我有一个方法/资源的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 }

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

我的Terraform资源为here as a Gist。希望这能完全显示我的API网关配置。

如果我测试从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下,产生{{} 1}}。

我可能误解了API网关基本路径映射和阶段是如何工作的,但CloudWatch告诉我该呼叫至少正在发生,尽管由于一些不明原因而失败:

/v1/status.json

显然,只有 整个V1阶段的流量才能通过CloudWatch日志。我在某个地方有一个错误的配置,我似乎无法找到它。

6 个答案:

答案 0 :(得分:8)

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

{
  "statusCode": 200
}

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

答案 1 :(得分:1)

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

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

第二个问题由CloudWatch日志中的以下条目指示:

  

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

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

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

答案 2 :(得分:0)

这里特别奇怪的是,修复只是为每个阶段使用AWS CLI创建部署。显然,Terraform没有在更改时更新或重新进行部署,因此我的更改从未发生过。

答案 3 :(得分:0)

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

随后,我运行terraform plan并查看了我的OPTIONS定义与其定义之间的区别。鉴于AWS控制台创建的OPTIONS方法有效,我将应用更改。

使用{0.11或更高版本的terraform使得这成为可能,因为terraform plan的输出细节更加精细。

答案 4 :(得分:0)

我在CloudFormation中这样做。

我花了一些时间才能得到它,这里被接受的答案非常有帮助,但有点含糊,因此添加了更多信息。

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

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

答案 5 :(得分:0)

使用 Mock Integration Amazon API Gateway 有 2 个常见原因导致 500 Internal Server 错误。

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

    { "statusCode": }

注意:确保状态代码作为整数而不是字符串传递。

正确:200 错误:“200”

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

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

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