【AWS】HTTP API+Lambda+DynamoDBのチュートリアルをやってみた
API Gatewayのチュートリアルの中に「Lambda と DynamoDB を使用した CRUD API の構築」があったのでやってみました。HTTP APIを使用するチュートリアルです。
[1] DynamoDBテーブルの作成
idをプライマリキーに持つテーブルを作成します。
[2] Lambda関数の作成
チュートリアルは「Node.js」ですが、私は「Python」で作成しました。
DynamoDBへのアクセス権限を設定します。ポリシーテンプレートから「シンプルなマイクロサービスのアクセス権限」を選択します。
関数の作成後、チュートリアルのソースコードをPython用に変更します。
import json import boto3 from decimal import Decimal # DynamoDBのテーブルにアクセス dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('http-crud-tutorial-items') # Decimal型をJSONに変換するための関数 def json_serialize(obj): if isinstance(obj, Decimal): return float(obj) raise TypeError # Lambda関数のエントリーポイント def lambda_handler(event, context): statusCode = 200 headers = { 'Content-Type': 'application/json' } try: routeKey = event['routeKey'] if routeKey == 'DELETE /items/{id}': id = event['pathParameters']['id'] table.delete_item(Key={'id': id}) body = f"Deleted item {id}" elif routeKey == 'GET /items/{id}': id = event['pathParameters']['id'] body = table.get_item(Key={'id': id}) elif routeKey == 'GET /items': body = table.scan() elif routeKey == 'PUT /items': request = json.loads(event['body']) table.put_item(Item={ 'id': request['id'], 'price': request['price'], 'name': request['name'] }) body = f"Put item {request['id']}" else: raise ValueError(f"Unsupported route: {routeKey}") except Exception as err: statusCode = 400 body = err finally: body = json.dumps(body, default=json_serialize) return { 'statusCode': statusCode, 'body': body, 'headers': headers }
「Decimal型をJSONに変換するための関数」は以下の記事を参考にさせていただきました。
python3 で Decimal を JSON に変換 - Qiita
[3] HTTP APIを作成
統合から「Lambda」を選択し、Lambda関数は先ほど作成した関数の名称を入力します。
ルートは以下の4つを設定します。
- "GET /items/{id}":1つの項目を取得
- "GET /items":すべての項目を取得
- "DELETE /items/{id}":1つの項目を削除
- "PUT /items":1つの項目を追加
ステージはデフォルトのままとします。
APIの作成後に表示されるURLは、APIを実際に使うときに使用します。
[4] APIをテスト
[4-1] 項目を追加(PUT)
次のコマンドを実行します。[APIのURL]は自身が作成APIのURLに置き換えます。
curl -v -X "PUT" -H "Content-Type: application/json" -d ¥ "{\"id\": \"abcdef234\", \"price\": 12345, \"name\": \"myitem\"}" ¥ [APIのURL]/items
コマンド実行に成功すると、以下のような応答が返ってきます。
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)! * We are completely uploaded and fine < HTTP/2 200 < date: Sun, 11 Apr 2021 07:36:31 GMT < content-type: application/json < content-length: 20 < apigw-requestid: dm8H5jP6NjMEJ5g= < * Connection #0 to host [APIのURL] left intact "Put item abcdef234"* Closing connection 0
[4-2] すべての項目を取得(GET)
次のコマンドを実行します。
curl -v [APIのURL]/items
コマンド実行に成功すると、以下のような応答が返ってきます。
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)! < HTTP/2 200 < date: Sun, 11 Apr 2021 07:40:48 GMT < content-type: application/json < content-length: 515 < apigw-requestid: dm8wCh7itjMEP1w= < * Connection #0 to host [APIのURL] left intact {"Items": [{"price": 12345.0, "id": "abcdef234", "name": "myitem"}], "Count": 1, "ScannedCount": 1, "ResponseMetadata": {"RequestId": "VB23I48FNE4DLDH2F86H9IRHDVVV4KQNSO5AEMVJF66Q9ASUAAJG", "HTTPStatusCode": 200, "HTTPHeaders": {"server": "Server", "date": "Sun, 11 Apr 2021 07:40:48 GMT", "content-type": "application/x-amz-json-1.0", "content-length": "107", "connection": "keep-alive", "x-amzn-requestid": "VB23I48FNE4DLDH2F86H9IRHDVVV4KQNSO5AEMVJF66Q9ASUAAJG", "x-amz-crc32": "1550053751"}, "RetryAttempts": 0}}* Closing connection 0
[4-3] 1つの項目を取得(GET)
次のコマンドを実行します。
curl -v [APIのURL]/items/abcdef234
コマンド実行に成功すると、すべての項目を取得したときと似たような結果が返ってきます。
[4-4] 1つの項目を削除(DELETE)
次のコマンドを実行します。
curl -v -X "DELETE" [APIのURL]/items/abcdef234
コマンド実行に成功すると、以下のような応答が返ってきます。
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)! < HTTP/2 200 < date: Sun, 11 Apr 2021 07:45:54 GMT < content-type: application/json < content-length: 24 < apigw-requestid: dm9f8iGMNjMEPbA= < * Connection #0 to [APIのURL] left intact "Deleted item abcdef234"* Closing connection 0
[5] リソースの削除
以下のリソースを削除したら終了です。
- DynamoDBテーブル
- HTTP API
- Lambda関数
- Lambda関数のロググループ
- Lambda関数の実行ロール
終わりに
Node.jsをPythonに置き換えるところは時間がかかりましたが、それ以外はスムーズに行うことができました。今回は、curlコマンドでAPIにアクセスしたため、煩雑に感じました。ですが、ブラウザなどからUI経由でアクセスできるようにすれば、非常にお手軽で便利だなと思います。
出典
- アイキャッチはGerd AltmannによるPixabayからの画像