Header keys lose their case

it seems that there is a bug in response.headers.

for example, code below:

``` python
import requests
r = requests.get('http://docs.python-requests.org/en/latest/')
print r.headers._store
```

it will display as:

```
{'connection': ('connection', 'keep-alive'),
 'content-encoding': ('content-encoding', 'gzip'),
 'content-type': ('content-type', 'text/html'),
 'date': ('date', 'Fri, 30 Aug 2013 14:29:28 GMT'),
 'last-modified': ('last-modified', 'Tue, 27 Aug 2013 15:01:13 GMT'),
 'server': ('server', 'nginx/1.1.19'),
 'transfer-encoding': ('transfer-encoding', 'chunked'),
 'x-cname': ('x-cname', 'docs.python-requests.org'),
 'x-deity': ('x-deity', 'Chimera'),
 'x-loaded-deity': ('x-loaded-deity', 'Asgard'),
 'x-served': ('x-served', 'Nginx')}
```

but actually the headers should be:

```
{'connection': ('Connection', 'keep-alive'),
 'content-encoding': ('Content-Encoding', 'gzip'),
 'content-type': ('Content-Type', 'text/html'),
 'date': ('Date', 'Fri, 30 Aug 2013 14:29:28 GMT'),
 'last-modified': ('Last-Modified', 'Tue, 27 Aug 2013 15:01:13 GMT'),
 'server': ('Server', 'nginx/1.1.19'),
 'transfer-encoding': ('Transfer-Encoding', 'chunked'),
 'x-cname': ('X-Cname', 'docs.python-requests.org'),
 'x-deity': ('X-Deity', 'Chimera'),
 'x-loaded-deity': ('X-Loaded-Deity', 'Asgard'),
 'x-served': ('X-Served', 'Nginx')}
```

because the code comments said:

```
Use the lowercased key for lookups, but store the actual key alongside the value.
```

at file structures.py line 72.


Hmm, this is a puzzling one. I see the same behaviour as you, plus this oddity:

``` python
>>> r.raw.headers
{'x-served': 'Nginx',
 'content-encoding': 'gzip',
 'transfer-encoding': 'chunked',
 'connection': 'keep-alive',
 'server': 'nginx/1.1.19',
 'last-modified': 'Tue, 27 Aug 2013 15:01:13 GMT',
 'x-cname': 'docs.python-requests.org',
 'x-loaded-deity': 'Asgard',
 'date': 'Fri, 30 Aug 2013 14:59:27 GMT',
 'x-deity': 'Asgard', 'content-type': 'text/html'}
```

I wonder if urllib3 is lowercasing these.


It does. See [L244 of urllib3/response.py](https://github.com/shazow/urllib3/blob/master/urllib3/response.py#L244). I'm not totally convinced this is a bug. For the purposes of the comment, the phrase "the actual key" should more correctly read "the key that was added to the dictionary". The CID is functioning as intended.

@sigmavirus24, I don't feel like urllib3 is doing the wrong thing here. Do you agree?


It's been doing that for over a year so I would guess that this is perfectly fine otherwise we would have run into issues much sooner. In other words @Lukasa, I agree with you.


the reason why I report this bug is that I want to write a proxy based on web page, user directly input the URL in the site and web server fetch the page for user, this require the web server return the same headers back to user which get from remote server, of course, I can uppercase the header name by myself, just want to see if we can do this in requests library.


Well I can confirm one thing: This is not something requests will do for you. We specifically wrap the headers in a case insensitive dictionary. We have no need for the headers to come back cased as they are sent and most of our users don't need them that way either.


I consider this a bug. Traditionally, requests preserved the server's casing. I'm not sure what happened.


@kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.


@Lukasa, if you look at the blame on that file though, the change was a year ago. Something quite possibly may have changed but it isn't on that line of that file. It is probably somewhere else and in a change far more recent.


I'm not convinced we haven't been doing this wrong for a while. The change is definitely in urllib3: take a look at the headers on the urllib3 response. =)


This bug will probably stay open a little while until we can sort something out in shazow/urllib3#236, so I renamed it to a clear statement of the symptoms. That way, hopefully, we won't get too many reopens of this issue. =D


It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.

```python
>>> import requests

>>> r = requests.get('https://httpbin.org/response-headers?CaseDKeY=aValue')
>>> r.headers
{'Content-Length': '93', 'CaseDKeY': 'aValue',... 'Content-Type': 'application/json'}

>>> r = requests.get('https://httpbin.org/get', headers={'CaseDKeY': 'aValue'})
>>> r.request.headers
{'Connection': 'keep-alive', 'CaseDKeY': 'aValue',... 'User-Agent': 'python-requests/2.12.4'}
```