LocalStackを用いたS3オブジェクト登録API(API Gateway+Lambda)作成方法 メモ


  • LocalStackを用いて、S3バケットにオブジェクト登録を行うAPIをAPI Gateway + Lambdaで作成する方法についてメモする。

LocalStack及びS3 準備

  • こちらの手順でLocalStackとオブジェクト登録先のバケット(sample-bucket)を準備しておく。

API Gateway 準備

  • REST API を作成する

    • リソースID(id)を控える
    aws apigateway create-rest-api --name 'LambdaS3TestAPI' --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
    {
        "id": "A-Z2699261A-Z3",
        "name": "'LambdaS3TestAPI'",
        "createdDate": "2021-10-09T04:56:42.976000+00:00"
    }
    
  • ルートリソースID取得

  aws apigateway get-resources --rest-api-id A-Z2699261A-Z3 --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "items": [
          {
              "id": "8955626A-Z80",
              "path": "/",
              "resourceMethods": {
                  "GET": {}
              }
          }
      ]
  }
  • 子リソース追加

パス名:lambda_s3_test

  aws apigateway create-resource --rest-api-id A-Z2699261A-Z3 --parent-id 8955626A-Z80 --path-part lambda_s3_test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "id": "5A-Z12A-Z75998",
      "parentId": "8955626A-Z80",
      "pathPart": "lambda_s3_test",
      "path": "/lambda_s3_test",
      "resourceMethods": {
          "GET": {}
      }
  }

  • HTTPメソッド追加
  aws apigateway put-method --rest-api-id A-Z2699261A-Z3 --resource-id 5A-Z12A-Z75998 --http-method POST --authorization-type "NONE" --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "httpMethod": "POST",
      "authorizationType": "NONE"
  }

Lambda 準備

  • lambda_s3_test.py

S3バケットsample-bucketにJSONファイルをオブジェクトとして配置する。

  import boto3
  from boto3.session import Session
  from datetime import datetime


  session = Session(aws_access_key_id='dummy',
      aws_secret_access_key='dummy',
      region_name='ap-northeast-1'
  )

  s3 = session.resource(
      service_name='s3', 
      endpoint_url='http://localhost:4572'
  )

  def lambda_handler(event, context):

      bucket_name = 'sample-bucket'
      key = 'sample_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.json'
      body = '{"sample_key":"sample_value"}'

      s3.Bucket(bucket_name).put_object(Key=key, Body=body)

      return 's3 put JSON_FILE'
  • 上記ファイルをlambda_s3_test.zipにzip化する。

  • アップロード

  aws lambda create-function --function-name="sample-function" --runtime=python3.8 --role="arn:aws:iam::123456789012:role/service-role/lambda-sample-role" --handler=lambda_s3_test.lambda_handler --zip-file fileb://lambda_s3_test.zip --endpoint-url=http://localhost:4574 --profile=localstack
  • 起動
  aws lambda invoke --cli-binary-format raw-in-base64-out --function-name sample-function result.log --endpoint-url=http://localhost:4574 --profile=localstack
  {
      "StatusCode": 200
  }
  • 確認
  aws s3 ls s3://sample-bucket --endpoint-url=http://localhost:4572 --profile=localstack
  2021-10-09 11:25:03         29 sample_2021-10-09-02-25-03.json

※ファイルが配置されている。

API Gateway - Lambda設定

  • Lambda ARN確認
  aws lambda list-functions --endpoint-url=http://localhost:4574 --profile=localstack
  {
      "Functions": [
          {
              "FunctionName": "sample-function",
              "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:sample-function",
              "Runtime": "python3.8",
              "Handler": "lambda_s3_test.lambda_handler",
              "Timeout": 60,
              "Version": "$LATEST"
          }
      ]
  }
  • API Gateway - Lambda設定
  aws apigateway put-integration --rest-api-id A-Z2699261A-Z3 --resource-id 5A-Z12A-Z75998 --http-method POST --type AWS_PROXY --integration-http-method POST --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:sample-function/invocations --passthrough-behavior WHEN_NO_MATCH --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack 
  {
      "type": "AWS_PROXY",
      "httpMethod": "POST",
      "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:sample-function/invocations",
      "integrationResponses": {
          "200": {
              "statusCode": 200,
              "responseTemplates": {
                  "application/json": null
              }
          }
      }
  }
  • 設定デプロイ
  aws apigateway create-deployment --rest-api-id A-Z2699261A-Z3 --stage-name test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "id": "6271136713",
      "description": "",
      "createdDate": "2021-10-09T05:08:40.688000+00:00"
  }

動作確認

  • APIリクエスト

パス:/restapis/${REST_API_ID}/test/_user_request_/${登録したAPIパス名}

POST /restapis/A-Z2699261A-Z3/test/_user_request_/lambda_s3_test HTTP/1.1
Host: localhost:4567
Content-Type: application/json
Content-Length: 2

{}
  • APIレスポンス
"s3 put JSON_FILE"
  • S3オブジェクト確認
aws s3 ls s3://sample-bucket --endpoint-url=http://localhost:4572 --profile=localstack
2021-10-09 11:25:03         29 sample_2021-10-09-02-25-03.json
2021-10-09 13:43:27         29 sample_2021-10-09-04-43-27.json
2021-10-09 14:14:53         29 sample_2021-10-09-05-14-53.json

※オブジェクトが追加されている。

参考情報