#32299 closed Bug (fixed)
MiddlewareNotUsed leaves undesired side effects when loading middleware in ASGI context
Reported by: | Hubert Bielenia | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | HTTP handling | Version: | 3.1 |
Severity: | Release blocker | Keywords: | |
Cc: | Andrew Godwin, Carlton Gibson | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I experienced strange issues when working with ASGI , django-debug-toolbar and my own small middleware. It was hard problem to debug, I uploaded an example project here: https://github.com/hbielenia/asgi-djangotoolbar-bug (the name is misleading - I initially thought it's a bug with django-debug-toolbar).
The SESSION_FILE_PATH
setting is intentionally broken to cause a 500 error. When starting the application and accessing /admin
(any location really, but I wanted to leave it at a minimum and didn't add any views) it gives TypeError: object HttpResponse can't be used in 'await' expression
. Commenting out asgi_djangotoolbar_bug.middleware.DummyMiddleware
fixes the issue (in that I receive a 500 ImproperlyConfigured
exception). I'm not sure about the overall role of django-debug-toolbar here - removing it causes Daphne to return a 500 error page but without debug information and there's no traceback in console either. I decided to leave it since it helped me approximate the causes of issue.
I notice that in https://github.com/django/django/blob/3.1.4/django/core/handlers/base.py#L58 while MiddlewareNotUsed
causes the loop to skip futher processing and go to next middleware, it does leave handler
variable overwritten with output of self.adapt_method_mode()
. On next pass, this handler
is passed to next middleware instance, disregarding all the previous checks for (lack of) async support. This likely causes the middleware chain to be "poisoned" from this point onwards, resulting in last middleware in response cycle to return an HttpResponse as a synchronous middleware would, instead of coroutine that is expected.
This is probably avoided by adding async support to my middleware, but unless I'm missing something docs indicate it should work as it is. It is my intention that it's applied only on synchronous requests, so I didn't make it async compatible on purpose. If it's intentional in Django that every middleware needs to support async if the application is run as ASGI app, the documentation should probably state that clearly. Though it kinda defeats the purpose of having async_capable = False
flag in the first place.
Change History (5)
comment:1 by , 4 years ago
Cc: | added |
---|---|
Component: | Uncategorized → HTTP handling |
Owner: | changed from | to
Severity: | Normal → Release blocker |
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:3 by , 4 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Many thanks for the detailed report.