aws-powertools / powertools-lambda-python

A developer toolkit to implement Serverless best practices and increase developer velocity.
https://docs.powertools.aws.dev/lambda/python/latest/
MIT No Attribution
2.84k stars 389 forks source link

Add APIGateway*EventModelV2 to parser #434

Closed xpayn closed 3 years ago

xpayn commented 3 years ago

I think that being able to use the parser module with APIGatewayV2 would be a nice little ergonomic improvement. today my code looks like:

def lambda_handler(event: Dict[str, Any], context: LambdaContext) -> Dict[str, Any]:
    event: APIGatewayProxyEventV2 = APIGatewayProxyEventV2(event)
    ...

It's not a big diffence but I think it looks better like this

@event_parser(model=APIGatewayProxyEventModelV2)
def lambda_handler(event: APIGatewayProxyEventModelV2, context: LambdaContext) -> Dict[str, Any]:
    ...

If you accept PR and I have some spare time, I'll try to make something. Thx

heitorlessa commented 3 years ago

Hey @xpayn - Absolutely, I'd love to help with any guidance if you can make a PR.

michaelbrewer commented 3 years ago

@heitorlessa note, we would have to ensure the any of the data classes are json serializable (ie: Idempotent handler expects a dict or something that can be serialized to json)

heitorlessa commented 3 years ago

@heitorlessa note, we would have to ensure the any of the data classes are json serializable (ie: Idempotent handler expects a dict or something that can be serialized to json)

Sure, it'd need an additional check if it's a Pyndantic Model, then you can call .json() to do the serialization of all of their custom types and such: https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeljson

ran-isenberg commented 3 years ago

@xpayn @heitorlessa if you havent started it yet, i can do it this week.i created the v1 one and this was on my todo list

ran-isenberg commented 3 years ago

see https://github.com/awslabs/aws-lambda-powertools-python/pull/441

xpayn commented 3 years ago

I was planning to make the PR today, I just wanted to review my code before, but i'll read your's instead

michaelbrewer commented 3 years ago

see #441

Seems like we are mixing things here. I think @xpayn is referring to the Event Source Data Classes.

michaelbrewer commented 3 years ago

Note, @xpayn there is also https://awslabs.github.io/aws-lambda-powertools-python/latest/core/event_handler/api_gateway/

michaelbrewer commented 3 years ago

@xpayn @risenberg-cyberark

Below is what i mean as an equivalent implementation for event source data classes (all of the in fact), and you would also benefit from the utility methods like get_header_value

@lambda_handler_decorator
def event_source(
  handler: Callable[[Any, LambdaContext], Any], 
  event: Dict[str, Any], context: LambdaContext, 
  data_class: Type[DictWrapper],
):
   # Where `model` is the passed in event source data class like APIGatewayProxyEventV2.
   return handler(data_class(event), context)

Usage wise, it would look like this

from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEventV2

@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext) -> Dict[str, Any]:
    assert event.get_header_value("x-foo") == "Foo"

To test:

lambda_handler({"headers": {"X-Foo": "Foo"}},  None)
michaelbrewer commented 3 years ago

@heitorlessa @xpayn @risenberg-cyberark created then equivalent for the event source data classes see PR #442 .

NOTE: This also fixes usage of data classes along the idempotent handler.

michaelbrewer commented 3 years ago

note that the event_parser has to be currently placed after the idempotent handler (and not before) otherwise you will get the following error:

@event_parser(model=APIGatewayProxyEventV2Model)
@idempotent(persistence_store=persistence_layer)
def lambda_handler(event, _):
   ...

Will raise a TypeError

>       raise TypeError(f'Object of type {o.__class__.__name__} '
                        f'is not JSON serializable')
E       TypeError: Object of type APIGatewayProxyEventV2Model is not JSON serializable

See how this was resolved for the event_source implementation :

@event_parser(model=APIGatewayProxyEventV2Model)
@idempotent(persistence_store=persistence_layer)
def lambda_handler(event, _):
   ...
heitorlessa commented 3 years ago

hey @xpayn - this is now available as part of 1.17.0 🎉 - I've added an example using both Model and Envelope for HTTP API: https://github.com/awslabs/aws-lambda-powertools-python/releases/tag/v1.17.0

Big thanks to @risenberg-cyberark on the implementation