0
0

More than 1 year has passed since last update.

APIgateway+Lambda+DynamoDB でのID管理を実装する

Last updated at Posted at 2022-10-16

目的

AWSでよくある構成として APIgateway+Lambda+DynamoDBのサーバレスな構成があります。
ただこの時に、DynamoDBでは連番の管理ができない(id1の次は2のidをつけるみたいな)
そのため、DynamoDB側でテーブルを二つ用意してあげる必要があります。

  • データを格納テーブル(例: id,名前,email,時刻など)
  • 連番を管理するテーブル(上記のidの部分をカウントするようのテーブル)

そのためLambdaでカウントするようなコードの書き方になってきます。
前提としてLambda,APIgateway,DynamoDB間のAMIの権限周りは既にクリアした前提とします。

やったこと

今回は、Lambdaのコード周りでハマりまくったので
備忘録的な感じでコードだけとりあえず貼っておきます。

import json
import boto3
import base64
import time
import decimal

# DynamoDBオブジェクト
dynamodb = boto3.resource('dynamodb')

# 連番を更新して返す関数
def next_seq(table, tablename):
    response = table.update_item(
        Key={
        'tablename' : tablename
        },
        UpdateExpression='set seq = seq + :val',
        ExpressionAttributeValues= {
            ':val' : 1
        },
        ReturnValues='UPDATED_NEW'
    )
    return response['Attributes']['seq']

    
def lambda_handler(event, context):
    try:
        # シーケンスデータを得る
        seqtable = dynamodb.Table('kuruma-sequence')
        nextseq = next_seq(seqtable, 'kuruma-user')
        
        # フォームに入力されたデータを得る
        body = event['body']
        if event['isBase64Encoded']:
            body = base64.b64decode(body)
            
        decoded = json.loads(body)
        username = decoded['username']
        email = decoded['email']
        
        # クライアントのIPアドレスを得る
        host = event['requestContext']['identity']['sourceIp']
        
        # 現在のUNIXタイムスタンプを得る
        now = time.time()
        
        # ユーザーテーブルを登録する
        usertable = dynamodb.Table('kuruma-user')
        usertable.put_item(
            Item={
                'id' : nextseq,
                'username' : username,
                'email' : email,
                'accepted_at' : decimal.Decimal(str(now)),
                'host' : host
            }
        )
        
        # 結果を返す
        return {
            'statusCode' : 200,
            'body' : json.dumps({})
        }
    except:
        # エラー文を返す
        import traceback
        err = traceback.format_exc()
        print(err)
        return{
            'statusCode' : 500,
            'headers' :{
                'context-type' : 'text/json'
            },
            'body' : json.dumps({
                'error' : '内部エラーが発生しました'
            })
        }

しょうもないところでハマった

クライアント側のIPアドレスを取得する時に書き方がわからずハマった。
最初はずっと下記のような書き方をしていました。
ですがずっと KeyError 'host'でひっかかっている
ドキュメントみても'host'はあったので何がいけないのかわからずで、Lambda側のテストの中身見ていると'identity'になっていたので、試しに書き換えてみると取得できるようになっていました。

ハマっていたコード
# クライアントのIPアドレスを得る
        host = event['requestContext']['host']['sourceIp']

成功したコード
# クライアントのIPアドレスを得る
        host = event['requestContext']['identity']['sourceIp']
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0