LoginSignup
67
67

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-09-17

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完了の画面に飛ばしてやる必要があります。このあたりの説明はまたそのうち。

67
67
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
67