普段、ちょっとしたデータの取得、加工などにAPI Gatewayを使用してLambdaを使用しているのですが、かなりやっつけで開発していたコードで、正常系は問題なく動いていたのですが、エラー時に Lambdaが返したHTTPレスポンスコードが API Gatewayに連携されず、Lambdaが5XX系エラーを返しているのに、API Gatewayが200 OK を 返していたと言う不具合がありました。
Lambdaの統合レスポンスをうまくマッピングしてやれば解消するのですが、
Lambdaプロキシ統合
を使用すればもっと簡単にできそうだったので、その内容をメモしておきます。
今回の対応はAWSの以下の内容を参照して試しました。
Lambdaプロキシ統合の設定
Lambdaプロキシ統合を使用すると、 API GatewayからLambdaへの値の受け渡しの方法が自動化され、個別にパススルーなどの設定することなくAPI Gateway - Lambdaがイイ感じに使用できます。
Lambdaプロキシ統合を使用すると、リクエストパラメータの渡し方やレスポンスの受け取り方が通常と異なるので注意が必要です。
今回は GET メソッドをプロキシ統合で設定した例を示します。 どの言語でも内容は変わりませんが、Lambdaはnodeで書きました。
API Gateway -> Lambdaへのリクエストデータの渡し方
API Gateway -> Lambdaへのデータの受け渡しは以下のフォーマットに従う必要があります。
例えば、API Gatewayから GETリクエストをパラメータ付きで行った場合、Lambda側は以下のようなフォーマットとなります。
API Gatewayからのリクエスト
GET https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/getapi?param1=111¶m2=222
Lambda側での受け取り
{ "resource": "Resource path", "path": "Path parameter", "httpMethod": "GET", "headers": {}, "multiValueHeaders": {}, "queryStringParameters": { "param1": "111", "param2": "222" }, "multiValueQueryStringParameters": {}, "pathParameters": {}, "stageVariables": {}, "requestContext": {}, "body": "{}", "isBase64Encoded": false }
上記のように、 queryStringParameters
に含まれてLambdaに渡されます。
Lambda -> API Gateway へのレスポンスデータの渡し方
Lambda -> API Gatewayへのデータの受け渡しは以下のフォーマットに従う必要があります。
const lambda_response_format = { "isBase64Encoded": false, "statusCode": 200, "headers": {}, "body": "json string" }
body の中には、jsonをstringにしたものを入れてやれば、そのまま API Gatewayにbodyやステータスが連携されます。ステータスコード statusCode
もそのままAPI Gatewayのレスポンスとして返ります(これがやりたかった)。
使用してみた所感
レスポンスがパススルーの設定することなくAPI Gatewayと連動するのは楽と感じる一方で、 若干リクエストやレスポンスのフォーマットを合わせるのに少し戸惑いました。
例えば通常の API Gatewayから /api?param1=111
のようなパラメータ渡しの場合 通常のパススルー(nodeの例)だと event.param1
のようにアクセスできますが、 プロキシ統合だと event.queryStringParameters.param1
のように受け渡し方法が変化するので、その辺りを留意すれば問題ないと感じました。
また、そもそもの話として、軽いAPIをサクッと作りたい場合、 API Gateway - Lambda間のやり取りは意識しないようにできれば良いのかなと思います。この辺りがやりたいだけならGCP(Firebase)のCloud Functionの方が手っ取り早いかもしれません。もしくは以前軽く触れたNetlifyのFunctionsなどを使えば静的コンテンツも含めてサクッとできたりしないかなと期待しています。