AWS SAMでAWS LambdaとAPIGatewayの基本的なテンプレート解説です。
SAMプロジェクト一覧
「sam init」を行うと、以下のようなファイルが生成されます。
└── sam-app
├── events
│ └── event.json
├── print
│ ├── app.py #Lambda実装本体
│ ├── Dockerfile
│ ├── __init__.py
│ └── requirements.txt #依存関係を定義
├── __init__.py
├── README.md
├── samconfig.toml
├── template.yaml #アプリケーションテンプレート
└── tests
├── __init__.py
└── unit
├── __init__.py
└── test_handler.py
template.ymlの内容
「AWSTemplateFormatVersion」はCloudFormationのテンプレートバージョンです。
現時点ではこのバージョンしかないので固定です。
「Transform」はCloudFormationに変換するためのマクロを指定します。
独自のマクロを使用しないのであればこのバージョン固定です。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: xxxxx #説明
パラメータ、グローバルセクション
パラメータはSAMのコマンドから受け取ることが出来ます。
サンプル内で活用はしていませんが、環境を切り替えるためにdev,stg, prodパラメータを受け取るようにしています。
グローバルセクションではテンプレート全体の共通設定をしたい場合に記載します。
参考:AWS SAM テンプレートのグローバルセクション
# 入力パラメータ
Parameters:
# デプロイ環境
Env:
Description: Enter environment.dev, stg, or prod.
Type: String
AllowedValues:
- dev
- stg
- prod
Default: dev
# 共通定義
Globals:
# Lambda関数用
Function:
Timeout: 180
Runtime: python3.7
# APIGateway用
Api:
# CORS有効化
Cors:
# 認証情報を含めることが可能か
AllowCredentials: False
# 許可するメソッド
AllowMethods: "'OPTIONS,POST,GET'"
# 許可するヘッダー文字列
AllowHeaders: "'authorization,Content-Type'"
# 許可するオリジン
AllowOrigin: "'*'"
# CORS プリフライトリクエストをキャッシュする秒数
MaxAge: "'180'"
Mappingsセクション
環境切替時にそれぞれの環境固有の値などを定義します。
# 環境切替用の定義。Envで切替
Mappings:
EnvMap:
dev:
DynamoDbEndpoint: "http://dev:8000"
stg:
DynamoDbEndpoint: "http://stg:8000"
prod:
DynamoDbEndpoint: "http://prod:8000"
Mappingsの値を参照する場合は以下のようにキーを指定します。
Environment:
Variables:
DYNAMODB_ENDPOINT: !FindInMap [EnvMap, !Ref Env, DynamoDbEndpoint]
Resourcesセクション
各リソースの詳細を定義していきます。「Type」では以下のリソースタイプが指定出来ます。
AWS SAM リソースおよびプロパティのリファレンス
「AWS::Serverless::Function」はLambda関数を表します。
# リソース定義
Resources:
DemoAppDeployment:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref ApiGatewayApps
# ------------------------------------
# Lambda関数定義
#-------------------------------------
PrintFunction:
Type: AWS::Serverless::Function
Properties:
# 関数名を指定
FunctionName: PrintFunction
# 関数コードのS3URL、またはローカルパス
CodeUri: print/
Handler: app.lambda_handler
# 開発用エイリアス(dev)を作成しバージョニングを有効にする。
# 開発用は常に最新バージョンを参照する。
AutoPublishAlias: dev
#この関数をトリガーするイベントを指定
Events:
Print:
Type: Api
Properties:
Path: /app/{proxy+}
Method: ANY
RestApiId: !Ref ApiGatewayApps
# ------------------------------------
# APIGateway定義
#-------------------------------------
# 「AWS::Serverless::Api」の場合、デフォルトでAPI統合タイプはLambda統合になる。
ApiGatewayApps:
Type: AWS::Serverless::Api
Properties:
Name: Apps
StageName: !Ref Env
EndpointConfiguration:
Type: "REGIONAL"
Outputsセクション(任意)
このセクションは任意ですが、他のスタックから値を参照したい場合に定義します。
Outputs:
ApiGatewayApps:
Value: !Sub "https://${ApiGatewayApps}.execute-api.${AWS::Region}.amazonaws.com/${Env}/app/print"
PrintFunction:
Value: !GetAtt PrintFunction.Arn```
Lambdaの実装とテスト
LambdaのPythonサンプルコードです。
リクエスト本文(body),パスパラメータ、クエリ文字列、ヘッダーから
値を取り出して、文字列を組み立ててレスポンスとして返却します。
import json
import ast
def lambda_handler(event, context):
body = event['body']
body= ast.literal_eval(body)
name = 'nobody' if not body['name'] else body['name']
device = 'pc' if not event['pathParameters']['proxy'] else event['pathParameters']['proxy']
price = '0' if not event['queryStringParameters']['price'] else event['queryStringParameters']['price']
company = 'disney' if not event['headers']['company'] else event['headers']['company']
parameters = name + ', ' + device + ', ' + price + ', ' + company
print('parameters: ', parameters)
res = {}
res["parameters"] = parameters
return {
'statusCode': 200,
'headers': {
"x-custom-header": "custom header value",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
'body': json.dumps(res),
'isBase64Encoded': False
}
APIGatewayのANYのメソッドテストで以下のような値をセットしてテストを実行します。
設定箇所 | 設定値 |
メソッド | POST |
パス | |
クエリ文字列 | price=evening |
ヘッダ | company:amazon |
リクエスト本文 | { “name”:”Mike” } |
テストを実行するとステータス200で以下のようなレスポンスが返されればOKです。
{
"parameters": "Mike, print, evening, amazon"
}
参考記事
- AWS Serverless Application Model 入門ハンズオンシリーズ
- CORS(Cross-Origin Resource Sharing)について整理してみた
- API Gateway の Lambda プロキシ統合のCORS対応をまとめてみる
- REST API リソースの CORS を有効にする
以上