Repository navigation
feat(event_handler): support Depends() injection in function-based middleware - #8573
leandrodamascena merged 4 commits into
Conversation
…ddleware Resolve Depends() parameters and Request injection for function-based middleware in MiddlewareFrame and AsyncMiddlewareFrame, sharing the per-request dependency cache via app.context so a dependency used by both middleware and route is resolved only once. Class-based middleware is intentionally out of scope for this change. Refs aws-powertools#8348
|
Thanks a lot for your first contribution! Please check out our contributing guidelines and don't hesitate to ask whatever you need. |
|
Hey @abhinavs1920, this looks great, thanks for the quick turnaround! I ran it locally with a few extra scenarios and it all holds up. Before you take it out of draft, could you add a short section to the docs ("Combining middleware and Depends()" in |
…te-level middleware tests
|
Thanks for the quick look! All three are in: the docs section with the DAO example from the issue, the title is fixed, and there are now tests for Router-level and route-level middleware with Depends (required_dependencies suite still green). Ready for your final review whenever works. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #8573 +/- ##
========================================
Coverage 96.93% 96.93%
========================================
Files 318 318
Lines 16005 16031 +26
Branches 1420 1423 +3
========================================
+ Hits 15514 15540 +26
Misses 349 349
Partials 142 142 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
leandrodamascena
left a comment
There was a problem hiding this comment.
Thanks @abhinavs1920, this came out really well. I ran it with the current develop merged in and a few extra cases on top of your tests: forward-ref annotations, class-based middleware, functools.partial, bound methods, **kwargs, Request with validation on, and a ServiceError raised inside a middleware dependency, which now returns 401 thanks to #8568. All good. I pushed a small test for the bound-method path to cover the last two lines codecov flagged. Approving.
|
|
Awesome work, congrats on your first merged pull request and thank you for helping improve everyone's experience! |
|
Awesome work, congrats on your first merged pull request and thank you for helping improve everyone's experience! |
|
Thanks for the careful review, and for adding the bound-method test to close out the codecov gaps. Enjoyed working through this one. |



Issue number: closes #8348
Summary
Changes
Function-based middleware can now declare
Depends()parameters and aRequestparameter, the same way route handlers can:MiddlewareFrame(sync) andAsyncMiddlewareFrame(async, both the coroutine and sync-in-thread paths) resolveDepends()parameters before calling the middleware.app.contextand shared with the route adapters, so a dependency used by both middleware and route is resolved only once.dependency_overridesandRequestinjection work for middleware dependencies.Route's caching, so there is no per-request overhead.User experience
Before: a middleware declaring
Annotated[UserDao, Depends(get_user_dao)]was called without that parameter being resolved, so the pattern from the issue (DAO injection into middleware) did not work.After: the issue's example works as written - the dependency is resolved and injected, and shares its cache with route dependencies.
Testing
tests/functional/event_handler/required_dependencies/test_middleware_depends.pycovering the acceptance criteria from the issue discussion: overrides, Request injection, sync + async middleware, short-circuit, single resolution across middleware and route, plus the issue's DAO example and a no-dependency backwards-compat check.tests/functional/event_handler/required_dependencies/: 511 passed.tests/functional/event_handler/suite: passes except 2 failures in_pydantic/test_http_resolver_pydantic.pyASGI concurrency tests, which also fail on unpatcheddevelop(pre-existing, unrelated).@leandrodamascena - opening this early draft as you offered. Happy to iterate.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.