どうしても毎度長いタイトルになってしまうなぁと思いつつ、表題のとおりで、AWSのAPI Gateway + Lambdaをつかって、クエリ文字列を取れるcloudformation用のテンプレートファイルの記述の仕方についてメモ。長い。
設定ファイル
/users/{user_id}?t=hogehoge のように、t=hogehogedeでクエリ文字列を取るようなAPI、updateUserを作成したいとする。
関数はpython3.6で、users/update_uesr.py(ハンドラの関数はlambda_handler)に置いてあるとする。その時、aws cloudformation packageをかけるtemplate.yamlは以下のように書ける。リージョンやらタイムアウトやらの設定はよしなに。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
UpdateUser:
Type: AWS::Serverless::Function
Properties:
CodeUri: users/
Environment:
Variables:
TABLE_NAME: テーブル名
Handler: update_user.lambda_handler
MemorySize: 256
Role: arn:aws:iam::ロール名
Runtime: python3.6
Timeout: 5
Api:
Type: 'AWS::Serverless::Api'
Properties:
StageName: prod
DefinitionBody:
swagger: "2.0"
info:
version: "1.0"
title: "API Gatewayで使う名前"
schemes:
- "https"
paths:
/users/{user_id}:
put:
produces:
- "application/json"
parameters:
- name: "user_id"
in: "path"
required: true
type: "string"
- name: "t"
in: "query"
required: true
type: "string"
responses:
"200":
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
x-amazon-apigateway-request-validator: "クエリ文字列パラメータおよびヘッダーの検証"
x-amazon-apigateway-integration:
uri: !Sub arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/${UpdateUser.Arn}/invocations
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Origin: "'*'"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
options:
consumes:
- "application/json"
produces:
- "application/json"
responses:
"200":
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
Access-Control-Allow-Methods:
type: "string"
Access-Control-Allow-Headers:
type: "string"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
requestTemplates:
application/json: "{\"statusCode\": 200}"
passthroughBehavior: "when_no_match"
type: "mock"
UpdateUserPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref updateUser
Principal: apigateway.amazonaws.com
まぁだいたい見たら書き換えるところもわかるはず。optionsはプリフライトリクエストのために作っている。最後のUpdateUserPermissionはAPI GatewayからLambdaを動かすためのパーミッション。
Lambdaの起動イベントとしてAPIを指定しているが、これはSAMならばもっと簡潔にかける。最初、クエリパラメータのために入れていたのだけれど、特にAPI Gatewayで検証しなくてもLambdaで受け取れることを後で知った。ただまぁ、Cognitoと連携させようとか考えると、結局swagger形式になってしまうのかなぁと思う。
設定ファイルの書き方は、ひとまずGUIのコンソールマネジメントで作って、作ったものをAPI Gatewayでエクスポートして中身を見るのが一番勉強になる感じ。
コメント