[Django] #32023: request.headers doesn't get updated when request.META is updated

13 views
Skip to first unread message

Django

unread,
Sep 21, 2020, 5:30:42 AM9/21/20
to django-...@googlegroups.com
#32023: request.headers doesn't get updated when request.META is updated
-----------------------------------------+------------------------
Reporter: lieryan | Owner: nobody
Type: New feature | 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 |
-----------------------------------------+------------------------
Currently, Django docs recommended using `request.headers` instead of META
to access headers, however the behaviour of `request.headers` currently
makes it hard to use correctly during tests.

Currently, the following code fails:

{{{
request.META["HTTP_USER_AGENT"] = "foobar"
assert request.headers["User-Agent"] == "foobar" # works
request.META["HTTP_USER_AGENT"] = "django"
assert request.headers["User-Agent"] == "django" # fails
}}}

This is because `request.headers` is a `@cached_property` that is
initialised when request.headers is first accessed, so underlying changes
to META don't get reflected to `request.headers`.

In regular Django request, this isn't that big of a deal, because arguable
`request.META` should be immutable anyway, and you probably should be
cursed if you modify `request.META` in production code.

However, this is rather annoying when writing tests, because often you
want to reuse the same request object to pass to different methods, or you
want to test the same method with slightly different header value. Due to
this caching, you have the option of either recreating the request from
scratch, which can be complicated if parts setting up META is spread
between `setUp()` and the test method, or you'd have to delete the
`request.headers` to force it to reinitialise, which is rather non obvious
and error prone, since you might forget to delete it and cause some tests
to pass/fail when they shouldn't.

Also, `request.headers` is read only, which means that you still have to
use the WSGI environment names when setting headers in tests rather than
the standard HTTP name.

I'd propose `HttpHeaders` should be reimplemented so that it isn't a real
collection, but just an accessor for `request.META`, also that
`HttpHeaders` should implement `__getitem__()` which should also update
`request.META`.

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

Django

unread,
Sep 21, 2020, 6:25:21 AM9/21/20
to django-...@googlegroups.com
#32023: HttpRequest.headers doesn't get updated when request.META is updated.
-------------------------------+--------------------------------------
Reporter: lieryan | Owner: nobody
Type: New feature | Status: closed

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

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 felixxm):

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


Comment:

Thanks for this ticket, however IMO it's not a desired change.
`HttpRequest.headers` are read-only and immutable by design (see
[https://github.com/django/django/pull/10171#issuecomment-440420179
comment]), moreover `META` contains more than only HTTP headers so
modifying `META` via `headers` would be misleading. If you need a low-
level modifications in your tests I would recommend to access/modify
`META` directly.

You can start a discussion on DevelopersMailingList if you don't agree.

--
Ticket URL: <https://code.djangoproject.com/ticket/32023#comment:1>

Django

unread,
Feb 26, 2024, 7:10:28 AM2/26/24
to django-...@googlegroups.com
#32023: HttpRequest.headers doesn't get updated when request.META is updated.
-------------------------------+--------------------------------------
Reporter: lieryan | Owner: nobody
Type: New feature | Status: closed
Component: HTTP handling | Version: 3.1
Severity: Normal | Resolution: wontfix
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 Chris Wesseling):

Replying to [comment:2 Carlton Gibson]:
> I'd guess you'd be able to `del request.headers` to reset the property
in your test.

Modification of META is documented behaviour:
https://docs.djangoproject.com/en/dev/ref/request-
response/#django.http.HttpRequest.get_host

Shouldn't `request.META.__setitem__` and `request.META.__delitem__` `del
request.headers` to synchronize if the key starts with `"HTTP_"`? In the
current code, if any middleware has peeked into `request.headers`, the
data gets out of sync on mutation.
--
Ticket URL: <https://code.djangoproject.com/ticket/32023#comment:3>
Reply all
Reply to author
Forward
0 new messages