Help us understand the problem. What is going on with this article?

HTMLフォームからAPIGatewayを使ってAWS LambdaにPOSTする

More than 3 years have passed since last update.

AWSのフォーラム内で質問されている内容を日本語で解説した記事になります。
参考リンク: https://forums.aws.amazon.com/thread.jspa?messageID=663593&tstart=0#663593

前提

HTMLフォームによるPOSTリクエストでは、各inputタグの内容をkey=valueの形式として&でつないだものがリクエストボディとして送信されます。

<form action="./endpoint">
  <input type="text" name="hoge" value="fuga"/>
  <input type="text" name="piyo" value="ihr"/>
  <input type="submit" value="送信">
</form>

---

hoge=fuga&piyo=ihr

しかし、Lambda function ではJSON形式での入力を期待しているため、デフォルトのままではHTMLフォームのバックエンドとして、APIGatewayおよびLambdaを利用することができません。

{
  "hoge": "fuga",
  "piyo": "ihr"
}

そこでAPIGatewayのMapping Templateを使います。

設定方法

  1. Amazon API Gatewayを適当な名前で作成します
  2. 好きなResouceに対してPOSTメソッドを作成します
  3. Integration type に "Lambda function" を選択し、Lambda functionがあるregionを指定します
  4. 作成後、"Integration Request" → "Mapping Templates" → "Add mapping template"とクリックしていきます
  5. Content-Type に "application/x-www-form-urlencoded" を設定し"Mapping template"として下記を保存します
## convert HTTP POST data to JSON for insertion directly into a Lambda function

## first we we set up our variable that holds the tokenised key value pairs
#set($httpPost = $input.path('$').split("&"))

## next we set up our loop inside the output structure
{
#foreach( $kvPair in $httpPost )
 ## now we tokenise each key value pair using "="
 #set($kvTokenised = $kvPair.split("="))
 ## finally we output the JSON for this pair and add a "," if this isn't the last pair
 "$kvTokenised[0]" : "$kvTokenised[1]"#if( $foreach.hasNext ),#end
#end
}

全てのデータが正しく入力された状態のPOSTしかこないのであれば、上記の簡易verで問題ありませんが、一部のデータが空白だったりした場合にうまく動作しなくなります。
その場合は、下記を使います。

## convert HTML FORM POST data to JSON for insertion directly into a Lambda function

## get the raw post data from the AWS built-in variable and give it a nicer name
#set($rawPostData = $input.path('$'))

## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawPostData.length() - $rawPostData.replace("&", "").length())

## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
 #set($rawPostData = $rawPostData + "&")
#end

## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawPostData.split("&"))

## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])

## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
 #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
 #if ($countEquals == 1)
  #set($kvTokenised = $kvPair.split("="))
  #if ($kvTokenised[0].length() > 0)
   ## we found a valid key value pair. add it to the list.
   #set($devNull = $tokenisedEquals.add($kvPair))
  #end
 #end
#end

## next we set up our loop inside the output structure "{" and "}"
{
#foreach( $kvPair in $tokenisedEquals )
  ## finally we output the JSON for this pair and append a comma if this isn't the last pair
  #set($kvTokenised = $kvPair.split("="))
 "$kvTokenised[0]" : #if($kvTokenised[1].length() > 0)"$kvTokenised[1]"#{else}""#end#if( $foreach.hasNext ),#end
#end
}

この設定をしておけば、下記ようなフォームのPOSTリクエストが、良い感じにJSONにマッピングされてLambda functionを呼び出すことができます。

<form action="https://example.execute-api.us-east-1.amazonaws.com/production/mytestform" method="POST">
  <input type="text" name="hoge" value="fuga">
  <input type="text" name="ihr" value="buiyon">
</form>

---
{
  "hoge": "fuga",
  "ihr": "buiyon"
}

ちなみに

フォームからPOSTする部分まではできましたが、APIのレスポンスをどうするかについての説明を省略しています。このままだとフォームに投稿後、ブラウザにAPIのレスポンスのJSONがそのまま表示されてしまうため、レスポンスについても適宜マッピングをしてやったり、302レスポンスを返してPOST完了の画面に飛ばしてやる必要があります。このあたりの説明はまたそのうち。

prog-8
オンラインプログラミング学習サービス「Progate」を開発・運営するスタートアップ
https://prog-8.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした