Bugs: Content-Length not updated by reused urllib.request.Request / has_header() case-sensitive

Terry Reedy tjreedy at udel.edu
Mon Nov 12 22:35:32 CET 2012

On 11/12/2012 10:52 AM, Johannes Kleese wrote:
> Hi!
> (Yes, I did take a look at the issue tracker but couldn't find any
> corresponding bug, and no, I don't want to open a new account just for
> this one.)

You only have to open a tracker account just once. I am reluctant to 
report this myself as I do not use the module and cannot answer questions.

> I'm reusing a single urllib.request.Request object to HTTP-POST data to
> the same URL a number of times. While the data itself is sent as
> expected every time, the Content-Length header is not updated after the
> first request. Tested with Python 3.1.3 and Python 3.1.4.

3.1 only gets security fixes. Consider upgrading. In any case, suspected 
bugs need to be tested with the latest release, as patches get applied 
daily. As it happens,

import urllib.request
opener = urllib.request.build_opener()
request = urllib.request.Request("http://example.com/", headers =
         {"Content-Type": "application/x-www-form-urlencoded"})

opener.open(request, "1".encode("us-ascii"))
print(request.data, '\n', request.header_items())

opener.open(request, "123456789".encode("us-ascii"))
print(request.data, '\n', request.header_items())

exhibits the same behavior in 3.3.0 of printing ('Content-length', '1') 
in the last output. I agree that that looks wrong, but I do not know if 
such re-use is supposed to be supported.

> While at it, I noticed that urllib.request.Request.has_header() and
> .get_header() are case-sensitive,

Python is case sensitive.

> while HTTP headers are not (RFC 2616, 4.2).
 > Thus the following, slightly unfortunate behaviour:
>>>> request.header_items()
> [('Content-length', '1'), ('Content-type',
> 'application/x-www-form-urlencoded'), ('Host', 'example.com'),
> ('User-agent', 'Python-urllib/3.1')]
>>>> request.has_header("Content-Type")
> False
>>>> request.has_header("Content-type")
> True
>>>> request.get_header("Content-Type")
# this return None, which is not printed
>>>> request.get_header("Content-type")
> 'application/x-www-form-urlencoded'

Judging from 'Content-type', 'User-agent', 'Content-length', 'Host', 
urllib.request consistently capitalizes the first word of all header 
tags and expects them in that form. If that is not standard, it should 
be documented.

Terry Jan Reedy

More information about the Python-list mailing list