[Django] #32586: ASGI responses from Django do not provide lowercased HTTP headers as required by the spec

5 views
Skip to first unread message

Django

unread,
Mar 23, 2021, 9:32:19 AM3/23/21
to django-...@googlegroups.com
#32586: ASGI responses from Django do not provide lowercased HTTP headers as
required by the spec
-----------------------------------------+------------------------
Reporter: Andrew Myers | Owner: nobody
Type: Bug | Status: new
Component: HTTP handling | Version: 3.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
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.

--
Ticket URL: <https://code.djangoproject.com/ticket/32586>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 23, 2021, 3:33:25 PM3/23/21
to django-...@googlegroups.com
#32586: ASGI responses from Django do not provide lowercased HTTP headers as
required by the spec
---------------------------------+--------------------------------------
Reporter: Myers Carpenter | Owner: nobody

Type: Bug | Status: new
Component: HTTP handling | Version: 3.1
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+--------------------------------------
Changes (by Mariusz Felisiak):

* 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>

Django

unread,
Mar 23, 2021, 5:42:39 PM3/23/21
to django-...@googlegroups.com
#32586: ASGI responses from Django do not provide lowercased HTTP headers as
required by the spec
---------------------------------+--------------------------------------
Reporter: Myers Carpenter | Owner: nobody

Type: Bug | Status: new
Component: HTTP handling | Version: 3.1
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+--------------------------------------

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>

Django

unread,
Mar 23, 2021, 5:44:44 PM3/23/21
to django-...@googlegroups.com
#32586: ASGI responses from Django do not provide lowercased HTTP headers as
required by the spec
---------------------------------+--------------------------------------
Reporter: Myers Carpenter | Owner: nobody

Type: Bug | Status: new
Component: HTTP handling | Version: 3.1
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+--------------------------------------

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>

Django

unread,
Mar 24, 2021, 2:11:57 AM3/24/21
to django-...@googlegroups.com
#32586: ASGI responses from Django do not provide lowercased HTTP headers as
required by the spec
---------------------------------+--------------------------------------
Reporter: Myers Carpenter | Owner: nobody
Type: Bug | Status: closed

Component: HTTP handling | Version: 3.1
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+--------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* resolution: => invalid


Comment:

Thanks Andrew.

--
Ticket URL: <https://code.djangoproject.com/ticket/32586#comment:4>

Reply all
Reply to author
Forward
0 new messages