1

I am writing middleware that, when it receives a request containing a header 'Foo', modifies its value, before passing the request on.

Django makes direct assignment illegal, so these do not work:

request.headers['Foo'] = 'bar'
request['Foo'] = 'bar'

I do have a working solution, but it's a bit hacky:

request.headers.__dict__['_store']['foo']=('Foo','bar')

Is there a cleaner way of doing it that I've missed?

2
  • 1
    You can use new_request = request.headers.copy(), and then modify the new request params. Commented Mar 31, 2020 at 14:09
  • request.headers is a better way to access the headers that are contained in request.META. But it's read-only. So in fact, just modify request.META['HTTP_FOO']. Commented Mar 31, 2020 at 15:39

1 Answer 1

4

The HTTP headers are contained in request.META which is just a dictionary that you can read and write. In META the header names are prefixed with HTTP_ and uppercase. So to access the header 'Foo' you'd do:

request.META['HTTP_FOO'] = 'bar'

The headers property (cached property in fact) is just a convenient way to access the HTTP headers without having to worry about the prefix and uppercasing, but it's read-only.

To reset a cached property, just remove it from the instance's __dict__ like so:

request.__dict__.pop('headers', None)

This will make sure the method is called again next time it's accessed. I added None to the pop() to ensure this doesn't crash, since if it wasn't accessed, it won't be in __dict__. If you access it explicitly in your own code, then request.__dict__.pop('headers') is sufficient.

Sign up to request clarification or add additional context in comments.

7 Comments

This didn't work. It does indeed update the request.META dict, but it does not update the output of request.headers.
headers is a @cached_property so if it was accessed before you made the assignment, it wouldn't reflect the change.
Yes, it is accessed. I read the original value, process it, and then overwrite the original value with the processed value.
Then don't read the original value using headers. Use META. And make sure no middleware that comes before yours accesses headers. Your middleware should be probably right at the top.
Yeah, unfortunately I need middleware above this, so this solution seems very fragile. I guess I could do the thing I posted in the question, and also update the META dict for completeness. I know it's not pretty, but will it cause any problems?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.