web-dev-qa-db-ja.com

APIGatewayモック統合が500で失敗する

APIから呼び出すと機能するが、実際に呼び出すと機能しないメソッド/リソースのAPIGateway統合があります。

_$ 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_というURLではアクセスできません。 glhfstable、および_v1_で定義されたステージがあるので、それを置き換えると、異なる応答が表示されます。 200JSONブロブを返すダミー応答が必要なだけです。

リソースの私のTerraformは ここでは要点として です。うまくいけば、これは私のAPIGateway構成を完全に示しています。

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
_

どうやらonlyV1ステージを通過するトラフィックがCloudWatchログに到達しているようです。どこかに設定ミスがあり、見つからないようです。

9
Naftuli Kay

統合リクエスト設定のリクエストテンプレートを次のように変更してみてください。

{
  "statusCode": 200
}

API Gatewayは、 統合リクエストテンプレート の応答で返すステータスコードを探します。応答は、統合応答のマッピングテンプレートによって生成されます。テラフォームの設定から、統合リクエストテンプレートに出力jsonファイルを読み込んでいることがわかります。これは、APIGatewayが予期しないコンテンツです。

10
Stefano Buliani

構成に少なくとも2つの明確な問題があります。

まず、3つの基本パスマッピングの1つが、APIを呼び出そうとしている方法と一致しません。ベースパスはステージ名と同じである必要はありませんが、必要に応じて同じにすることができます。ベースパスマッピングにはベースパスとステージ名が含まれているため、API Gatewayは、呼び出しパスにステージではなくベースパスマッピングが含まれることを想定しているため、パスの[glhftablev1]部分をベースパスとして解釈して検索します。対応するベースパスマッピングエントリに対して、使用するAPIとステージを決定します。これは、500を返すv1およびglhfベースパスで正常に機能します(別の問題を示します)。安定したベースパス( https://api.naftuli.wtf/stable/status.json )は、ドメイン名apiに「stable」のベースパスが定義されていないため、403Forbiddenを返します。 naftuli.wtf。安定したステージは「最新の」ベースパスにマップされるため、 https://api.naftuli.wtf/latest/status.json を呼び出すことで安定したステージを呼び出すことができます。これは現在機能していません。理由はわかりません。これを実行しているリージョンを教えていただければ、構成を調べてさらに掘り下げることができます。

2番目の問題は、CloudWatchログからの次のエントリによって示されます。

構成エラーのため実行に失敗しました:statusCodeはリクエストテンプレートで定義された整数である必要があります

統合リクエストテンプレート(ファイル内の「$ {file( "$ {path.module} /files/status.json")}」の参照)に、最上位属性として「statusCode:200」が含まれていることを確認できますか。

また、リクエストテンプレートとレスポンステンプレートに同じファイルを使用しているのも驚きです。

1
MikeD at AWS

ここで特に奇妙だったのは、明らかに、修正は、各ステージでAWSCLIを使用してデプロイを作成することでした。どうやら、Terraformは変更時にデプロイメントを更新または再キックしていなかったため、変更が反映されませんでした。

0
Naftuli Kay

同じエラーが発生したので、この問題の解決に役立つのは、AWSコンソールでOPTIONSリクエスト定義を削除することでした。次に、コンソールの「Enable CORS」フォームに従って、新しいOPTIONSメソッドを作成しました。

その後、terraform planを実行し、OPTIONSの定義と彼らの定義の違いを調べました。 AWSコンソールで作成されたOPTIONSメソッドが機能したことを考慮して、変更を適用しました。

テラフォーム0.12以上を使用すると、terraform plan出力の詳細がより細かくなり、これが可能になります。

0
tjheslin1