見出し画像

Lambda + API Gatewayの初歩の初歩の初歩(レスポンス)で転んだ話

昔からプラモデルは説明書を読まずに組み合わせて後から絶望していました。反省が活かせていない。恥ずかしいけどまたやりそうなので備忘的に残します。

このごろAWSを久しぶりに触っているのですが、今まではCloud Watchのイベントスケジュール等でLambdaを殴って満足しておりました。ところがここにきて外部からのリクエストを受け付ける必要がでてきたので、3年くらい前に触ったAPI Gatewayの記憶を頼りに適当にLambdaとAPI Gatewayを繋いだら怒られました。

> Invoke-RestMethod -Uri $url -Method Get -Headers $token

Invoke-RestMethod : {"message": "Internal server error"}
発生場所 行:1 文字:1
+ Invoke-RestMethod -Uri $url -Method Get -Headers $token
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod]、WebException
   + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

API Gatewayのテスト画面でレスポンスを見てみると・・・

Sun Jun 09 05:54:05 UTC 2019 : Execution failed due to configuration error: Malformed Lambda proxy response
Malformed Lambda proxy response

おやおや、Lambdaからのレスポンスがおかしいって言われてますね。

exports.handler = async (event, context, callback) => {
   // TODO implement
   var responseBody = {
       "res1": "this is good response!"
   };

   const response = {
       statusCode: 200,
       body: responseBody
   };
   callback response;
};

もしかしてstatusCodeの返し方が違うの・・・?
と思ったら、ちゃんとドキュメントがありました。最初から読めばよかったですね。

body フィールドは、もし JSON を返すのであれば、それ以上のレスポンスの問題を防ぐために文字列に変換されなければなりません。JSON.stringify を使用すると、Node.js 関数でこれを処理できます。他のランタイムでは異なる解決方法が必要ですが、概念は同じです。

bodyはStringで渡しましょう。

そりゃそうだ。失礼しました。
ドキュメントに倣ってコードを修正。

exports.handler = async (event, context, callback) => {
   // TODO implement
   var responseBody = {
       "res1": "this is good response!"
   };

   var response = {
       "statusCode": 200,
       "headers": {
           "header1": "header-is-here"
       },
       "body": JSON.stringify(responseBody),
       "isBase64Encoded": false
   };
   callback(null, response);
};
> Invoke-RestMethod -Uri $url -Method Get -Headers $token

res1
----
this is good response!

ちゃんと動きました。めでたしめでたし。

いいなと思ったら応援しよう!