Description
Use case
Event Handler Router - Imrprovements
Currently the route endpoints of event_handler
don't take any function parameters other than url path variables as positional parameters
app = APIGatewayRestResolver()
@app.get("/todos/<todo_id>")
@tracer.capture_method
def get_todo_by_id(todo_id: str):
This makes it difficult for introducing many use-cases within the route as the body, query-params can be accessed from only the app
variable.
parser
utility is a great tool but cant be used readily with routes. For different endpoints in event_handler
the body might be different, in which case the event_parser doesn't help much as it can be applied only at the handler level.
A router_parser
utility would greatly help at the route function level, but due to the limitation mentioned about in the event_handler
the route functions aren't extendible.
Solution/User Experience
Passing the event
and context
to the routes as named arguments, will help overcome the limitation
User Experience
@app.route("/todos", method=["PUT", "POST"])
@tracer.capture_method
def create_todo(event: APIGatewayProxyEvent, context: LambdaContext):
todo_data: dict = event.json_body # deserialize json str to dict
todo: Response = requests.post("https://jsonplaceholder.typicode.com/todos", data=todo_data)
todo.raise_for_status()
return {"todo": todo.json()}
Change Proposed
app.resolve
invokes the route as shown here, requesting it to be changed to below
def _call_route(self, route: Route, args: Dict[str, str]) -> ResponseBuilder:
"""Actually call the matching route with any provided keyword arguments."""
try:
kwargs = {"event": self.current_event, "context": self.context}
return ResponseBuilder(self._to_response(route.func(**args, **kwargs)), route)
This change will pave to route_parser
like utilities that will help take away a lot of boiler plate implementation of pydantic
parser. It will also enable routes
to take full advantage of the parser utility, which is not the case today as parser decorators can only be applied at the handler
proposal for the route_parser would roughly look like this
@app.post("/todo")
@route_parser(model=Todo, envelope=envelopers.ApiGatewayEnvelope) # pydantic
def create_todo(data: Todo):
todo: Response = requests.post("https://jsonplaceholder.typicode.com/todos", data=data.dict())
# Returns the created todo object, with a HTTP 201 Created status
return {"todo": todo.json()}, 201
Alternative solutions
No response
Acknowledgment
- This feature request meets Lambda Powertools Tenets
- Should this be considered in other Lambda Powertools languages? i.e. Java, TypeScript
Metadata
Metadata
Assignees
Labels
Type
Projects
Status