-
-
Notifications
You must be signed in to change notification settings - Fork 932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move exception handling logic to endpoints #2020
Conversation
Tests aare failing for coverage reasons. I like how the diff shows very clearly what the real change is now so I opened a PR against this branch to show what a "cleaned up" version with no coverage issues would look like, but the diff is bigger: master...adriangb:starlette:cleanup-move-exc |
Will it work if we just wrap # starlette/routing.py
class BaseRoute:
async def __call__(self, scope, receive, send):
...
handler = ExceptionMiddleware(self.handle, handlers=scope['starlette.exception_handlers'], debug=scope['app'].debug),
await handler(scope, receive, send) If possible, this significantly reduces the code duplication. |
There’d still be two request instances. Reducing code duplication can be done easily with some refactoring (there is no duplicate code in master...adriangb:starlette:cleanup-move-exc) |
@tiangolo would you mind taking a look at this with respect to how it might impact FastAPI? You vendor |
I like it! 🚀 I agree it could/would be ported over to FastAPI. Thanks @adriangb for pinging me (and @Kludex for DMing about the ping, I tend to lose these important pings among too many GitHub email notifications 😬 ). A bit more from my point of view, probably taking this even further (in the future): I want to be able to support exception handlers at the router level, to have some routers that handle some specific exceptions that might be relevant only to some portions of the code related to that router, instead of having to put all the exceptions together at the global app. In FastAPI, this will also mean that I will have to refactor how |
Good to hear! I think if FastAPI is willing to adapt I don't see any blockers for moving forward with this; it's a backwards compatible change for pure-Starlette projects.
Interesting, this is not even something I had thought of! But yes of course this change would make it pretty straightforward to have per-route exception handlers that we could merge with the application or router level exception handlers using a |
Closing this in favor of #2026 (see #2020 (comment)) |
Fixes #493, partially resolves #1692 (comment), resolves #1649 (comment)
By moving handling of exceptions to the
Route
level we can use the sameRequest
/WebSocket
object for the endpoint and exception handlers.I wrote this PR so that it is backwards compatible (and it also needs a lot of polish). There's a lot of duplicate logic between
ExceptionMiddleware
androuting.py
. I see two options:ExceptionMiddleware
around. This is less likely to break things like FastAPI that poke around into the internals of Starlette. It also means that ASIG middleware e.g. in an ASGI app mounted viaMount
can continue to raiseHTTPException
s which will get caught byExceptionMiddleware
(I'd argue that anyone that is doing this should not be doing this but it's technically possible to do). (see note 1)ExceptionMiddleware
. We'd just need to move a bit of logic (separating the exception and status handlers and putting them into the scope for every request) intoStarlette
. This would eliminate all of the duplicate code.Implementation aside, to me this makes sense conceptually: exception handlers operate on requests/webscokets not at the ASGI level. So they should live within the sphere of Request/WebSocket, not alongside generic ASGI middleware. I think this is the same principle that applies to FastAPI's dependencies and why they don't have the problems that BaseHTTPMiddleware has.
Notes:
Starlette(..., middleware=...)
since those middleware have never had any guarantee ofHTTPException
s they raise being caught.