starlette icon indicating copy to clipboard operation
starlette copied to clipboard

Add Mount(..., middleware=[...])

Open adriangb opened this issue 3 years ago • 9 comments

  • Closes #1464

By @Kludex:

  • Closes #685
  • Related to #1286

adriangb avatar May 24 '22 11:05 adriangb

This would be really useful. Is there a plan to merge and release this still at some point?

tkrause avatar Jul 12 '22 03:07 tkrause

I'll review this before the next minor release.

Kludex avatar Jul 12 '22 04:07 Kludex

The implementation is simple and works well. However, there is a different behavior in both if an exception raised in handler.

This exception will be handled by ExceptionMiddleware and thus app-level middleware will still be able to change response such as appending extra tracking header. But this is not the case using router-level middleware (wherher #1649 or #1464).

I wonder if this behavior changing is expected and should be documented or we need build the middleware stack per Mount or Router? I currently remove the app-level middleware and wrap router-level middleware between ServerErrorMiddleware and ExceptionMiddleware.

progamesigner avatar Jul 20 '22 04:07 progamesigner

Great point @progamesigner

One option would be to add ExceptionMiddleware automatically if the user supplies any other middleware. But that would get awkward because the exception handlers wouldn't propagate from the application level, so you'd be left juggling two sets of exception handlers. Sounds like a footgun to me. So maybe the best thing we can do is simply document this behavior?

I think this really only applies to things that plan to modify or look at the response, right? If you are trying to modify the response (e.g. GZipMiddleware) you probably want the exceptions to just tear through you (no point in compressing a 404 response). In the cases where you want to inspect the response it may make sense to have the route level middleware just "mark" the request by adding a key into the scope like scope["foobar.log-request"] = True and then have an application level middleware be what is actually doing the heavy lifting. That way the route-level middleware contains the routing specific logic but doesn't have to handle errors and if another middleware modifies the response (e.g. by compressing it) it will happen before the response info gets logged (so the content-length won't be off and such).

adriangb avatar Jul 20 '22 13:07 adriangb

I added a note to the docs explaining https://github.com/encode/starlette/pull/1649#issuecomment-1189821544

adriangb avatar Aug 13 '22 15:08 adriangb

I'm going to check this tonight.

Kludex avatar Aug 31 '22 15:08 Kludex

I think we can take this opportunity to add a more real case usage instead of GZipMiddleware, maybe a middleware related to the issue that motivates this PR. What do you think?

Kludex avatar Sep 01 '22 05:09 Kludex

I think we can take this opportunity to add a more real case usage instead of GZipMiddleware, maybe a middleware related to the issue that motivates this PR. What do you think?

I was going to say yes but: https://github.com/encode/starlette/discussions/1837. So GZipMiddleware is actually a motivating example, right?

adriangb avatar Sep 01 '22 05:09 adriangb

I think we can take this opportunity to add a more real case usage instead of GZipMiddleware, maybe a middleware related to the issue that motivates this PR. What do you think?

I was going to say yes but: #1837. So GZipMiddleware is actually a motivating example, right?

  • I think the motivation was https://github.com/encode/starlette/issues/685, but fair enough. 👍

Kludex avatar Sep 01 '22 06:09 Kludex

I'm going to go ahead and merge it so we can proceed with the next release, if anyone has any last minute concerns we can address them in a separate PR before the release.

adriangb avatar Sep 21 '22 19:09 adriangb

A thought about this PR, Request objects and error handling. I wonder if we maybe should’ve had ExceptionMiddleware wrap each Route instead of being a middleware at the application level? That would have both resolved the concerns in https://github.com/encode/starlette/pull/1649#discussion_r962144793 and also https://github.com/encode/starlette/pull/1692#issuecomment-1266401636 because we’d be able to (1) make sure there is nothing in between ExceptionMiddleware and the route and (2) use the same Request object for error handlers and the endpoint. I wonder if this could be made backwards compatible…

adriangb avatar Jan 26 '23 02:01 adriangb