AWS SAMによる、Lambda統合のやり方
Summary
API Gatewayで受け取ったヘッダー情報をlambdaに流したいという用件があり、lambda統合(lambda integration)をSAMで行うことがあったのでその内容をまとめました。
Originの値を取りたいだとか、lambda側でIP制限を行いたい人とか参考にできるんじゃないかと思っています。
lambda統合とは?
lambda統合を行うことで、API メソッドを Lambda 関数に統合することができます。
前提条件
$ aws --version
aws-cli/2.2.5 Python/3.8.8 Darwin/20.4.0 exe/x86_64 prompt/off
@ sam --version
SAM CLI, version 1.21.1
$ node -v
12.22.1
$ volta -v
1.0.2
筆者はバージョン管理の兼ね合いでvoltaを使っていますが、特段入れる必要はありません。voltaをインストールしない場合は、package.json内の"volta": { ...
以下の部分は削除してください。
下準備
AWSのS3のus-east-1のリージョンで適当に名前をつけてバゲットを作成してください。
構成
フォルダ構成
.
├──src
│ └── index.ts
├── package.json
├── yarn.lock
├── node_modules
├── dist
└── template.yml
template.yml
Corsは*
にしています。ここの設定は適宜変えていただけると幸いです。
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Globals:
Api:
EndpointConfiguration: REGIONAL
Cors: "'*'"
Resources:
ExampleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs12.x
CodeUri: dist/
Events:
Handler:
Type: Api
Properties:
Path: /handler
Method: get
RestApiId:
Ref: ExampleAPIGateway
ExampleAPIGateway:
Type: AWS::Serverless::Api
DependsOn: ExampleFunction
Properties:
StageName: prod
DefinitionBody:
swagger: 2.0
info:
version: "1.0"
title: "Lambda Integration Example"
basePath: /prod
schemes:
- "https"
paths:
/handler:
get:
responses: {}
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExampleFunction.Arn}/invocations
passthroughBehavior: "when_no_match"
httpMethod: "POST"
type: "aws_proxy"
package.json
Summaryでも書きましたが、voltaを使わない人は"volta": {...
以下を削除してください。
また、--s3-bucket
の部分は下準備で作成したバケットの名前を入れてください。
{
"name": "lambda-integration-example",
"version": "1.0.0",
"description": "Lambda Integration Example for Typescript",
"main": "index.ts",
"scripts": {
"build": "yarn tsc -p ./tsconfig.json && cp ./package.json ./dist/package.json",
"deploy": "sam deploy --template-file template.yml --stack-name lambda-integration-example-add-your-name --s3-bucket lambda-integration-example-add-your-name --region us-east-1 --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND"
},
"dependencies": {
"aws-lambda": "^1.0.6"
},
"devDependencies": {
"@types/aws-lambda": "^8.10.85",
"typescript": "^4.4.4"
},
"keywords": [],
"author": "",
"license": "ISC",
"volta": {
"node": "12.22.1",
"yarn": "1.22.10"
}
}
index.ts
ここでは、APIを叩いてきた元のIPをbodyに入れてみたいと思います。
import { APIGatewayProxyHandler } from 'aws-lambda'
export const handler: APIGatewayProxyHandler = async(event) => {
console.info('headers', event.headers)
const ip = event.headers['X-Forwarded-For']
return {
statusCode: 200,
body: `IP is ${ip}, and handler is success`,
}
}
デプロイ
ルートディレクトリで実行してください。
$ yarn build
$ yarn deploy
上のコマンドを実行すると、おそらくAPI GatewayにLambda Integration Example
という名前でAPI Gatewayが作成されているかと思います。
上の写真のURLの呼び出し
と書いている部分にAPI GatewayのURLが生成されるので、下記のようにコマンドを入力してください。
$ curl https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/handler
IP is xxx.xxx.xxx.xxx, and handler is success
上のように呼び出し元のIPが表示されていると成功です。
最後に
lambda統合をSAMで行うという記事を書かせていただきました。
普段はフロントエンドをメインで書いているエンジニアなのですが、最近AWSを使うことが増えてきた&記事を書いてみるということをしてみたかった、のでこの度投稿させて頂きました。
今回初めて記事を書いたので、おそらく読みづらかったりするかもしれませんがそこは悪しからず。。。
今回の記事で使用したコードが含まれているレポジトリを載せておきます。
最後までお読み頂きありがとうございました。もし参考になった、良かったと思われる方はいいねボタンを押していただけると嬉しいです。
Thank you!
Discussion