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.
--
Ticket URL: <https://code.djangoproject.com/ticket/32586>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: Andrew Godwin, Carlton Gibson (added)
Comment:
This is explained in the
[https://github.com/django/django/blob/76c0b32f826469320c59709d31e2f2126dd7c505/django/core/handlers/asgi.py#L219-L220
comment]. Andrew, what do you think?
--
Ticket URL: <https://code.djangoproject.com/ticket/32586#comment:1>
Comment (by Andrew Godwin):
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.
--
Ticket URL: <https://code.djangoproject.com/ticket/32586#comment:2>
Comment (by Andrew Godwin):
The ASGI spec has been updated to reflect the actual situation here:
https://github.com/django/asgiref/commit/c1d3d97d212c6e6ba1c29905f38fa611c7269779
--
Ticket URL: <https://code.djangoproject.com/ticket/32586#comment:3>
* status: new => closed
* resolution: => invalid
Comment:
Thanks Andrew.
--
Ticket URL: <https://code.djangoproject.com/ticket/32586#comment:4>