API Gateway + Lambda にFormからPOSTする時のマッピングテンプレートを作成しました

API Gateway

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんばんは、菅野です。
また API Gateway + Lambda に関するブログエントリーとなります。
今回は API Gateway + Lambda にFormからPOSTする時のマッピングテンプレートを作成しました。

はじめに

API Gateway + Lambda を使った API に対し Form から Post して Lambda に値を渡すにはマッピングテンプレートを登録する必要があります。
その中でリクエストボディを Key と Value に分けるといった処理が必要になるので、どうやって値を取得するのか、どうやって分解すればいいのかを調べました。
同じような境遇の方や、Webサーバーから API Gateway + Lambda へ移行したいと思っている方は一度ご覧ください。

Content-Type について

Form からPOSTする場合に使われる Content-Type は主に以下の二つとなります。

  • multipart/form-data
  • application/x-www-form-urlencoded

API Gateway の「本文マッピングテンプレート」にはこの二つを登録します。
スクリーンショット 2016-06-16 22.30.12

API Gateway のマッピングテンプレートで使える情報について

AWSがドキュメントを用意してくれてますので一度見ておくことをおすすめします。
API Gateway API リクエストとレスポンスペイロードのマッピングテンプレートのリファレンス

Lambda に渡す必要のある情報は何か?

私が必要としたのは以下の情報でした。

  • リクエストボディ
    Form で入力された情報が受け取れないと意味がありません。
  • リクエストヘッダ(ヘッダフィールドの一覧)
    Authorization の情報が必要だったのと、その他情報が必要になる時の為に渡します。
  • 接続元IPアドレス
  • ユーザーエージェント
  • ステージ変数
    API Gateway にはステージというものが用意されていて、ステージ毎に用意されるURLが異なります。
    ステージ毎に設定できる固定値をステージ変数といい、それを Lambda に渡します。
    ステージ変数を渡す事によって、Lambda 側で処理を変えたりといった事が可能になります。
    スクリーンショット 2016-06-16 23.34.40

マッピングテンプレートでどこまで処理するか?

Lambda にプログラムを書くのは当然です。じゃあリクエストボディを Key と Value に分解するのも Lambda 側で処理するか?といった部分は個人の好みが影響します。
ですが、この先いくつもの Lambda 関数を書く度にリクエストボディを毎回毎回分解するのは嫌なので、必要な情報は eventオブジェクトに格納して簡単にアクセスできるようにします。

各情報の取得方法

情報 変数名 取得方法
リクエストヘッダ headers $input.params().header
リクエストボディ queryParameters $input.body
接続元IPアドレス sourceIp $context.identity.sourceIp
ユーザーエージェント userAgent $context.identity.userAgent
ステージ変数 任意の名前 $context.変数名

完成したマッピングテンプレート

以下のようなマッピングテンプレートを作成しました。
ステージ変数は「stage」という名前で設定してあります。

{
    "headers" : {
#foreach( $key in $input.params().header.keySet() )
       "$key" : "$input.params().header.get($key)"#if( $foreach.hasNext ),#end
#end
    },
    "queryParameters" : {
#set( $tmpstr = $input.body )
#foreach( $keyandvaluestr in $tmpstr.split( '&' ) )
#set( $keyandvaluearray = $keyandvaluestr.split( '=' ) )
        "$keyandvaluearray[0]" : "$keyandvaluearray[1]"#if( $foreach.hasNext ),#end
#end
    },
    "stage" : "$context.stage",
    "sourceIp" : "$context.identity.sourceIp",
    "userAgent" : "$context.identity.userAgent"
}

Lambda 側で情報にアクセスする方法(node.js)

マッピングテンプレートで設定した情報は全て eventオブジェクトに入っていますので以下のようにアクセスできます。

  • event.headers.Authorization
  • event.queryParameters.キー名
  • event.stage

さいごに

いかがでしたでしょうか。
私が API Gateway + Lambda で作成していた時に結構時間が掛かった部分をまとめてみました。
マッピングテンプレートにはプログラムを書けるので、そこそこ複雑な処理を行える所がなかなか面白いですよね。
今後も何かマッピングテンプレートを作成した時にはここでお伝えしていきます。
それではまた。

参考ページ

これらのページを参考にさせていただきました。
ありがとうございました。
API Gateway API リクエストとレスポンスペイロードのマッピングテンプレートのリファレンス
API Gatewayへの入力値にLambdaからアクセスする
HTMLフォームからAPIGatewayを使ってAWS LambdaにPOSTする

AWS Cloud Roadshow 2017 福岡