kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Powertools for AWS Lambda (Python) の Validation で UUID フォーマットをバリデーションする

Powertools for AWS Lambda (Python) の Validation でプロパティの「UUID フォーマット」をチェックする場合は以下のようにスキーマを実装すると良さそう👌

{
    '$schema': 'http://json-schema.org/draft-07/schema',
    'type': 'object',
    'required': ['id'],
    'properties': {
        'id': {
            'type': 'string',
            'pattern': '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
        },
    },
}

便利な Powertools for AWS Lambda (Python) の Validation に関しては前に紹介記事を書いた📝

kakakakakku.hatenablog.com

公式ドキュメントも参照📝

docs.powertools.aws.dev

検証環境

今回は AWS SAM を使って Amazon API Gateway (REST API) と AWS Lambda 関数を構築する.Amazon API Gateway に POST リクエストを送ってバリデーションロジックの確認をした❗️

動作確認

👾 template.yaml

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: powertools-validation-uuid
      CodeUri: src/
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      Layers:
        - arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:73
      Events:
        Api:
          Type: Api
          Properties:
            Path: /
            Method: POST

👾 app.py

今回はサンプルとしてパラメータが正常であれば 200 OK を返して,異常であれば 400 BAD_REQUEST を返すようにした.

import json
from http import HTTPStatus

from aws_lambda_powertools.utilities.validation import SchemaValidationError, envelopes, validate

SCHEMA = {
    '$schema': 'http://json-schema.org/draft-07/schema',
    'type': 'object',
    'required': ['id'],
    'properties': {
        'id': {
            'type': 'string',
            'pattern': '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
        },
    },
}


def main(event):
    try:
        validate(event=event, schema=SCHEMA, envelope=envelopes.API_GATEWAY_REST)
    except SchemaValidationError as e:
        return {
            'statusCode': HTTPStatus.BAD_REQUEST,
            'body': json.dumps({'message': e.validation_message}),
        }

    return {
        'statusCode': HTTPStatus.OK,
        'body': json.dumps({'message': 'ok'}),
    }


def lambda_handler(event, context):
    return main(event)


if __name__ == '__main__':
    with open('./events/event.json', 'r') as f:
        event = json.load(f)

    response = main(event)
    print(response['body'])

動作確認

ok

event.json

{
    "id": "92380de4-cfe1-4b9c-9a67-2928dcba10e0"
}

UUID Generator で取得した UUID を id プロパティに指定すると ok になった🙆‍♂

$ curl -s -X POST --data @event.json ${ENDPOINT}
{"message": "ok"}

data.id must match pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$

event.json

{
    "id": "92380de4-cfe1-4b9c-9a67-2928dcba10e00"
}

UUID 以外のフォーマット(1文字余分に追加した)で id プロパティを指定するとバリデーションエラーになった🙅‍♂️

$ curl -s -X POST --data @event.json ${ENDPOINT}
{"message": "data.id must match pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"}

JSON Schema 2019-09

ちなみに JSON Schema 自体はビルトインフォーマットとして uuid をサポートしているけど,Powertools for AWS Lambda (Python) の Validation で 'format': 'uuid' とスキーマを実装すると Unknown format: uuid というエラーが出てしまう🔥

json-schema.org

実は uuid フォーマットは JSON Schema 2019-09(1つ前は JSON Schema draft-07)でサポートされていて,Powertools for AWS Lambda (Python) の Validation が依存している fastjsonschema (Fast JSON schema for Python)draft-04draft-06draft-07 のみをサポートしているという背景があって現状では使えなかった📝

horejsek.github.io