yuheijotaki.com

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の設定
    • デプロイ
      • リソース > アクション > 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())
}

その他参考