API GatewayとAWS Lambda
はじめに
基本的な設定方法は以下のサイトを参考にしてください。
【API Gateway】AWS Lambda統合のPythonでHello, world
1.1. やろうとしていること
このパートでは、クライアントからの要求をAPI gatewayを通してLambdaで処理して何らかの反応を返すというもの
1.2. サービスの説明
1. API gatewayについて[1]
API gateway : APIの作成と管理が簡単にできるサービス
◯APIの作成:AWS Lambda、EC2、もしくはAWS外でパブリックとして公開されているアプリケーションをAPIとして公開することができます。
◯APIの管理:Amazon API Gatewayは、APIの管理に必要な以下のような事項をお客様側での実施が必要なく、AWS側で提供しています。
2. AWS Lambdaについて[2]
Lambda : AWSに関するなにかしらのイベントによって処理を実行する環境
関数として処理を定義する。
3. bottleについて
bottle : Pythonで一番軽量なWEBフレームワーク
lambda関数内の処理や、htmlの"form"から送られたpostの処理に利用する。特に考えるのはrequestオブジェクト。
各サブクラスについて
BaseRequestが親クラスとなって様々なサブクラスが作成される。
- query
- forms
- files
- params
- json
特に送信データが写真のときは__multipart/form-data__になる。その場合用いるのは"files"クラス
filesクラス
メソッド
- .get("KEY") : KEYに対応するVALUEのオブジェクトが取得できる
- .filename : ファイル名が取得できる
- .name : html内の"form"のnameが取得できる
- .file : fileObject(BytesIO buffer or temporary file)を開くことができる
1.3. サービスの設定方法
1. API gatewayの設定
- RESTfum APIの設定
- メソッドの設定
/(GET)
┗/check(POST)



2. Lambdaの設定
手順
- 利用するファイルをまとめて圧縮
- AWS Lambdaの設定
1. 利用するファイルをまとめて圧縮
今回使用したファイル集
・sample/
├ bottle.py # webフレームワーク
├ text_test.py # text送信の場合
├ photo_test.py # 画像送信の場合
└ views/ # htmlファイル
├ text_login.html
├ text_check.html
└ photo_login.html
各コードサンプル
1. テキストを送信する場合
text_test.py
# coding:utf-8
from bottle import template
import urllib
# htmlファイルを返す関数
def login(event, context):
return {
"statusCode": 200,
"headers": {"Content-Type": "text/html"},
"body": template('text_login')
}
# postされた情報を加えたhtmlファイルを返す関数
def check(event, context):
body = event['body']
# application/x-www-form-urlencordedから適切な形に変換する
body2 = urllib.parse.parse_qs(body)
username = body2['username'][0]
email = body2['email'][0]
return {
"statusCode": 200,
"headers": {"Content-Type": "text/html"},
"body": template('text_check', username=username, email=email)
}
text_login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>メールアドレスと名前を送信してください</h1>
<form method="post" enctype="application/x-www-form-urlencoded" action="/check">
<input placeholder="名前" name="username" type="text"/>
<input placeholder="メール" name="email" type="text"/>
<input value="送信" type="submit"/>
</form>
</body>
</html>
text_check.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>確認</h1>
<h2>名前</h2>
<p>{{ username }}</p>
<h2>メールアドレス</h2>
<p>{{ email }}</p>
</body>
</html>
2. 画像を送信する場合
photo_test.py
# coding:utf-8
from bottle import template
# htmlファイルを返す関数
def show_page(event, context):
return {
"statusCode": 200,
"headers": {"Content-Type": "text/html"},
"body": template('photo_login')
}
# postされた画像の生データを表示
def check(event, context):
photo_data = event['body']
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": {"message": photo_data}
}
photo_login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PhotoTest</title>
</head>
<body>
<h1>Test</h1>
<h2>画像を挿入してください</h2>
<form method="post" enctype="multipart/form-data" action="/photo">
<input placeholder="画像" name="photo" type="file" />
<input placeholder="送信" type="submit" />
</form>
</body>
</html>
- 注意:htmlファイルのformタグの”action”はAPI gatewayでの「APIのデプロイ」が完了してから追加記入すること。宛先が異なると正しく動作しない。
2. AWS Lambdaの設定
- 使うファイルをzipで圧縮
- AWS Lambdaサイト内の「関数の作成」にて関数を設定後、zipファイルを転送

1.4. 注意すべき部分
IAMロールについて
AWSのサービス(API gateway, Lambdaなど)を利用する際、権限を設定する必要がある。
一般には標準的なもので間に合うが、S3を用いたりEC2と通信したい場合は適切なIAMロールに変更する必要がある。
proxyと本文マッピングテンプレートについて
API gatewayではレスポンスの形を適切に変更することが可能である。主に2つの整形方法がある。
- プロキシ統合
- マッピングテンプレートの利用
今回は1.のプロキシ統合を用いた。これにより、レスポンスの形が統一されるためLambdaで処理する方法が統一されるからである。
ただ、2.であればレスポンスを適切な形に整形してLambdaに送れるため処理が用意になるというメリットもある。[3]
以下はformでpostしたデータを整形するためのマッピングテンプレートである。[4]
"queryParameters" : {
# set( $tmpstr = $input.body )
# foreach( $keyandvaluestr in $tmpstr.split( '&' ) )
# set( $keyandvaluearray = $keyandvaluestr.split( '=' ) )
"$keyandvaluearray[0]" : "$keyandvaluearray[1]"#if( $foreach.hasNext ),#end
# end
}
参考サイト
[1] 5分でわかるAmazon API Gateway
[2] AWS Lambda超入門
[3] API Gatewayの本文マッピングテンプレートを理解する
[4] API Gateway + Lambda にFormからPOSTする時のマッピングテンプレートを作成しました