Package: lambda-handler
Lambda HandlerThis project defines a Python class,LambdaHandler, and associated Pydantic-derived
event classes, for handling API Gateway events from a range of sources, in particular:Direct InvocationEventBridgeSQS queuesSNS topicsWhen not using the optional FastAPI support (see below), the package's only dependency
is pydantic.Usefromlambda_handlerimport(LambdaHandler,EventBridgeEvent,SnsEvent,LambdaResponse,)handler=LambdaHandler()@handler.sns(topic_name="MyTopic")defhandle_mytopic(event:SnsEvent)->LambdaResponse:body=frobincate()returnLambdaResponse(status_code=200,body=body)@handler.event_bridge(resource_name="MyResource")defhandle_myresource(event:EventBridgeEvent)->LambdaResponse:body=fizzbuzz()returnLambdaResponse(status_code=200,body=body)The handler looks after both the event parsing (so your functions should always
accept an event of some*Eventtype), and its response as a properly-formatted
dictionary.Combining with FastAPIA notable omission from the events that are handled byLambdaHandlerdirectly are
HTTP requests. These can be handled by an instance ofFastAPI, as follows:fromfastapiimportFastAPIfromlambda_handlerimportLambdaHandlerapp=FastAPI(title="My HTTP handler")@app.get("/")defindex():return"Hello, World!"handler=LambdaHandler(fastapi_app=app)The handler will then take care of everything on your behalf. If you'd prefer, you
can setfastapi_applater instead, and the handler will take care of that, too.fromfastapiimportFastAPIfromlambda_handlerimportLambdaHandler,SnsEvent,LambdaResponsehandler=LambdaHandler()@handler.sns(topic_name="MyTopic")defhandle_mytopic(event:SnsEvent)->LambdaResponse:body=frobincate()returnLambdaResponse(status_code=200,body=body)app=FastAPI(title="My HTTP handler")@app.get("/")defindex():return"Hello, World!"handler.fastapi_app=appFastAPI support requires the package to be installed with optional extras:pip install "lambda-handler[fastapi]", and is built on top of the existingMangumpackage.Model ValidationThe*Eventmodels lambda-handler defines usepydanticfor parsing and validation, and these models aregeneric. This means that you can
pass a type argument to the class when defining your function, and it will correctly
parse the content of the event (see below) to that type. If this is confusing, it's
easier to see it in action:fromlambda_handlerimportLambdaHandler,SnsEvent,LambdaResponsefrompydanticimportBaseModelhandler=LambdaHandler()classMyModel(BaseModel):thing:str@handler.sns(topic_name=topic_name)deftest_func(event:SnsEvent[MyModel])->LambdaResponse:assertisinstance(event.records[0].sns.message,MyModel)returnLambdaResponse(status_code="200")Here, we have parametrisedSnsEventwithMyModelin the signature oftest_func,
meaning that themessageattribute is parsed to aMyModelinstance in the process.Parametrised Event AttributesThe following attributes are those which are parsed to a Pydantic model for each event
type:Event TypeParsed AttributeDirectInvocationEventevent.direct_invocation.bodyEventBridgeEventevent.detailSnsEventevent.records[i].sns.messageSqsEventevent.records[i].bodyDealing with Raw DataIf you don't want to deal with parsed event objects, you can include theraw=Trueparameter to any of the wrapping methods ofLambdaHandlerand write a function
that accepts and returns aDict[str, Any]instead. Note that, in this case, the
event object will still be parsed by theAwsEventsubclasses for identification,
but the event object will be passed as-is in dictionary format to the function.fromfastapiimportFastAPIfromlambda_handlerimportLambdaHandler,SnsEvent,LambdaResponsefromtypingimportAny,Dicthandler=LambdaHandler()@handler.sns(topic_name="MyTopic")defhandle_mytopic(event:SnsEvent)->LambdaResponse:body=frobincate()returnLambdaResponse(status_code=200,body=body)@handler.sns(topic_name="MyOtherTopic".raw=True)defhandle_mytopic(event:Dict[str,Any])->Dict[str,Any]:body=frobincate()return{"statusCode":"200"}