この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
おはようございます、もきゅりんです。
個人的に、今月はAPI Gateway(REST) と仲良くなろう月間でした。
前回はこのようなまとめをしました。
今度こそ (REST) API Gateway と仲良くなるための個人的まとめ
今回のターゲットはプロキシ統合です。
プロキシ統合とは
プロキシ統合には、過去弊社記事にもこのようなものがあります。
API Gateway が「Lambda プロキシ統合」でさらに使いやすくなっててびっくりした話
API Gateway の Lambda プロキシ統合をセットアップする に記載されていることを簡潔にまとめると、Lambdaのプロキシ統合とは以下のようなものだと分かりました。
- クライアントの API リクエストをLambda 関数に raw リクエストをそのまま渡せること
- プロキシ統合のLambda 関数は決められた形式で返却する必要があること
- プロキシリソース {proxy+} とすべてのメソッドに対応する ANYメソッド を併用するとさらに強力であること
うん、なるほど(よく分からん)。
とりあえず便利なものということは伝わります。
ということで、では実際に、シンプルなLambdaの実装で、プロキシ統合と非プロキシ統合(カスタム統合)の両方を対応して比較してみることにしました。
チュートリアル: Lambda 非プロキシ統合で API Gateway API をビルドする
まずは、非プロキシ(カスタム)統合からやっていきます。
元ネタは、チュートリアル: Lambda 非プロキシ統合で API Gateway API をビルドする です。
やることとしては、パラメータを付与してPOSTなりすると、そのパラメータを使って以下のようなレスポンスをしてくれるものです。
{
"greeting": "Good {time}, {name} of {city}.[ Happy {day}!]"
}
Lambda関数の作成
公式のチュートリアルだとNode.jsなのですが、Python3.7に書き換えてます。(Node.jsを知らんので)
import json
DAYS = ['Sunday', 'Monday', 'Tuesday',
'Wednesday', 'Thursday', 'Friday', 'Saturday']
TIMES = ['morning', 'afternoon', 'evening', 'night', 'day']
print('Loading function')
def lambda_handler(event, context):
name = 'you' if not event['name'] else event['name']
city = 'World' if not event['city'] else event['city']
time = 'day' if not event['time'] in TIMES else event['time']
day = None if not event['day'] in DAYS else event['day']
# Generate a greeting
greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '
if day:
greeting += 'Happy ' + day + '!'
# Log the greeting to CloudWatch
print('Hello: ', greeting)
dic = {}
dic["greeting"] = greeting
return json.dumps(dic)
API Gatewayの設定
APIの作成は、チュートリアル通りなので、引っかかりそうな点以外は省いていきます。
(API Gateway Cors の有効化を選択します。とは書かれていますが、特に有効化しなくても問題なかったです。)
リソースからメソッドが作成できます。
メソッドリクエストの設定では、HTTPのリクエストメッセージのどの部分をパラメータとして受け取るかを設定していきます。
モデルとマッピングテンプレートの項で、何だこれは?となりますが、下記を参照して確認していきます。
リクエストおよびレスポンスマッピングのモデルおよびマッピングテンプレートを作成する
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "GetStartedLambdaIntegrationInputModel",
"type": "object",
"properties": {
"callerName": { "type": "string" }
}
}
上記のモデルの中身については、
"$schema": "http://json-schema.org/draft-04/schema#"
は、データモデル JSON schema draft 4
を使っている、type は object で、propertiesオブジェクトに callerName を string で設定しますよ、というものですね。
マッピングテンプレートは、Velocity Template Language (VTL) というスクリプトで表されるテンプレートで、ここでは、前段のメソッドリクエストの形式をLambdaにわたす前に変換する役割です。
リクエストされた各パラメータからそれぞれのkeyに値を当てはめ、リクエストボディの中身からcallerName("John")を取得してjsonにする、というものです。
#set($inputRoot = $input.path('$'))
{
"city": "$input.params('city')",
"time": "$input.params('time')",
"day": "$input.params('day')",
"name": "$inputRoot.callerName"
}
それでは、下記のパラメータをセットしてテストしてみましょう。
- メソッド:
POST
- パス:
Seattle
- クエリ文字列:
time=morning
- ヘッダー:
day:Wednesday
- リクエスト本文:
{ "callerName":"John" }
問題ないようなので、適当なステージ名でデプロイして、curlします。
curl -X POST \
'https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/Seattle?time=evening' \
-H 'content-type: application/json' \
-H 'day: Thursday' \
-d '{
"callerName": "John"
}'
"{\"greeting\": \"Good evening, John of Seattle. Happy Thursday!\"}"%
テスト同様、返ってきました。
なるほどなるほど。これがカスタム統合。
Lambda プロキシ統合で API Gateway API をビルドする
同じ内容を今度はプロキシ統合で対応してみます。
Lambda関数の作成
プロキシ統合では、Lambdaの返却方法と受け取り方が決まっているので、 *1先のPython3.7のコードを修正します。
import json
import ast
DAYS = ['Sunday', 'Monday', 'Tuesday',
'Wednesday', 'Thursday', 'Friday', 'Saturday']
TIMES = ['morning', 'afternoon', 'evening', 'night', 'day']
print('Loading function')
def lambda_handler(event, context):
body = event['body']
body= ast.literal_eval(body)
name = 'you' if not body['name'] else body['name']
city = 'World' if not event['pathParameters']['proxy'] else event['pathParameters']['proxy']
time = 'day' if not event['queryStringParameters']['time'] else event['queryStringParameters']['time']
day = None if not event['headers']['day'] in DAYS else event['headers']['day']
# Generate a greeting
greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '
if day:
greeting += 'Happy ' + day + '!'
# Log the greeting to CloudWatch
print('Hello: ', greeting)
dic = {}
dic["greeting"] = greeting
# Output Format
return {
'statusCode': 200,
'headers': {
"x-custom-header": "my custom header value"
},
'body': json.dumps(dic),
'isBase64Encoded': False
}
API Gatewayの設定
リソースを作成して、プロキシリソースを選択すると、勝手に入力されます。 CORS有効化はいりません。
保存すると、Lambdaの場合、関数入れるだけの状態です。
下記パラメータをセットしてテストします。
- メソッド:
POST
- パス:
LosAngels
- クエリ文字列:
time=evening
- ヘッダー:
day:Friday
- リクエスト本文:
{ "name":"Michael" }
問題ないようなので、デプロイして、curlします。
curl -X POST \
'https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/LosAngels?time=evening' \
-H 'content-type: application/json' \
-H 'day: Friday' \
-d '{
"name": "Michael"
}'
{"greeting": "Good evening, Michael of LosAngels. Happy Friday!"}%
ほへー! 確かに、手間なく手早くお手軽設定できる、という便利さがわかりました!
でもカスタム統合も個人的には味わい深さがありましたので、もっと味わいたくなりました。
API Gateway とちょっとナカヨクナレタカナ。
以上です。
どなたかのお役に立てば幸いです。