GASからAWS API Gateway(Lambda)へリクエスト送信、ファイルをS3へアップ
GAS → API Gatewayのリクエストのみ(レスポンスなし)でJSONファイルをS3へアップロードする。
主な手順
- S3バケットを作成
- 権限作成
- 該当バケットへの
s3:PutObject
ポリシー作成 - ロールにポリシーをつけて作成
- 該当バケットへの
- Lambda
- 実行ロールに先程作成したロールを付与
- 関数作成
- デプロイ
- テスト
- Execution resultsが200で成功することを確認
- テスト
- デプロイ
- API Gateway
- リソース作成
- REST APIで作成し、
- APIキーを有効化する場合(今回は割愛)
- APIキー > アクション > APIキーの作成
- 使用量プラン > 作成
- リソース > APIキーの必要性 をtrueにしてキー選択
- WAFの設定
- WAFのページからIPセットを作成しておく
- ステージ > 該当ステージ > 設定 > ウェブアプリケーションファイアウォール (WAF) から設定
- デプロイ
- リソース > アクション > APIのデプロイ
- リソース作成
- GAS
- JSONファイルを作成する(今回は割愛)
UrlFetchApp()
でリクエストを投げる
コード
ポリシー
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ExampleStmt", "Action": [ "s3:PutObject" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::MY-BACKET-NAME/*" ] } ] }
Lambda
少しハマった点として、object putする際に ContentType='application/json'
など明示的に指定をしないと、Lambda側で自動でContentTypeが設定されてしまう。
参考: python - AWS Content Type Settings in S3 Using Boto3 - Stack Overflow
lambda_function.py
import json import boto3 s3 = boto3.resource('s3') # バケット名を指定 BUCKET_NAME = "MY-BACKET-NAME" def lambda_handler(event, context): # request_idを取得 request_id = context.aws_request_id # バケット名、オブジェクト名を指定 bucket = s3.Bucket(BUCKET_NAME) object_key_name = "PATH/MY-JSON-NAME.json" # オブジェクトを生成 obj = bucket.Object(object_key_name) # 対象のバケットにjsonデータをアップロード json_data = event r = obj.put(Body = json.dumps(json_data), ContentType='application/json') return { 'request_id': request_id, 'statusCode': 200, }
GAS
function uploadS3() { const endpoint = 'MY-API-END-POINT' const json = JSON.stringify({"key1": "value1"}) const params = { 'method' : 'post', 'contentType': 'application/json', 'payload' : json }; const req = UrlFetchApp.fetch(endpoint, params) Logger.log(req.getContentText()) }