Opened 4 years ago
Closed 4 years ago
#32586 closed Bug (invalid)
ASGI responses from Django do not provide lowercased HTTP headers as required by the spec
Reported by: | Myers Carpenter | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | Andrew Godwin, Carlton Gibson | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Every time HTTP headers are talked about in the ASGI spec it always says: "Header names must be lowercased."
They never explain why they should be in lowercase, which maybe is a bug in the spec, but it turns out http headers are to be treated case insensitively https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive
Using Django 3.1.7 and uvicorn and adding a ASGI middleware like this:
class SpamMiddleware: def __init__(self, app): self.app = app async def __call__(self, scope, receive, send): print(f"start {scope!r}") async def send_wrapper(message): print(f"send {message!r}") return await send(message) async def receive_wrapper(): message = await receive() print(f"receive {message!r}") return message return await self.app(scope, receive_wrapper, send_wrapper)
you can see that django does not follow the spec:
send {'type': 'http.response.start', 'status': 200, 'headers': [(b'Content-Type', b'application/javascript; charset="utf-8"'), (b'X-Frame-Options', b'DENY'), (b'Vary', b'Cookie'), (b'Content-Length', b'189761')]}
A possible fix (and I would be happy to make a PR) is to add a call to .lower()
on the header name on https://github.com/django/django/blob/76c0b32f826469320c59709d31e2f2126dd7c505/django/core/handlers/asgi.py#L227
The upside, beyond being spec compliant, would be that middleware that need to filter/modify headers wouldn't need to apply .lower()
themselves.
This all came up because I'm attempting to add the zerocopysend extension to uvicorn and middleware to translate the X-Sendfile header from django-sendfile2 to using zerocopysend.
Change History (4)
comment:1 by , 4 years ago
Cc: | added |
---|
comment:2 by , 4 years ago
Unsurprisingly, I agree with the way Django currently implements it, since I wrote it - the ASGI spec is in the wrong here, and I'll fix that separately.
comment:3 by , 4 years ago
The ASGI spec has been updated to reflect the actual situation here: https://github.com/django/asgiref/commit/c1d3d97d212c6e6ba1c29905f38fa611c7269779
This is explained in the comment. Andrew, what do you think?