Feature request: APIGatewayRestResolver decorator support for class methods (use case: constructor injection)
Use case
I'd like to decorate class methods with APIGatewayRestResolver's router.
Particularly, I want to use constructor injection in my app. Support dependency injection in lambda parameters is good prerequisite reading.
Here is illustrative code. We have a GET that queries Dynamo with animal_id and returns a JSON response:
class App:
resolver = APIGatewayRestResolver()
def __init__(
self,
dynamo_client: DynamoClient = DynamoClient(ANIMAL_TABLE)
):
self.dynamo_client = dynamo_client
@resolver.get("/animal/<animal_id>")
def get_animal(self, animal_id):
result = self.dynamo_client.get_item_by_key("animal_id", animal_id)
payload = json.dumps(result.get("data", []))
return Response(
status_code=HTTPStatus.OK,
content_type=content_types.APPLICATION_JSON,
body=payload,
)
def lambda_handler(event, context):
return App().resolver.resolve(event, context)
Currently I get the following error:
missing 1 required positional argument: 'self'
which indicates self argument isn't being passed. So I believe APIGatewayRestResolver router can't decorate class methods.
Solution/User Experience
Solution is probably:
- Configure the decorator to pass
self
Alternative solutions
Another solution is to simply use method injection as described by @heitorlessa in Support dependency injection in lambda parameters. This negates the benefits of constructor injection, which is useful when multiple methods share a client, for example.
Acknowledgment
- [X] This feature request meets Lambda Powertools Tenets
- [ ] Should this be considered in other Lambda Powertools languages? i.e. Java, TypeScript
Thanks for opening your first issue here! We'll come back to you as soon as we can. In the meantime, check out the #python channel on our AWS Lambda Powertools Discord: Invite link
Hey @harwoodjp if you have the bandwidth, I'd welcome a PR for this.
The issue is that route method was implement as a closure not an actual decorator that could handle both functions and classes (it's different for classes, specially when preserving identity).
It's something I've been wanting to refactor but didn't get the bandwidth yet. Class support decorators is becoming a new ask so we should support this, expand the Middleware Factory utility, and more recently allow the new Middleware support with Classes in mind.
Appreciate any help here and can guide any step if you have the bandwidth too.
Thanks a lot!
Adding 'triage' label so we revisit it in upcoming iterations
I have completed an initial POC pass at API Middleware for ApiRestResolver - the middleware supports any python Callable structure including a class implementing the __call__ method. Maybe this would address the feature request here? I feel middleware addresses a lot of issues currently in the log that are old so commenting here to try and collate them all.
PR: #2917