Issue 16464: urllib.request: opener not resetting content-length (original) (raw)
Code based on python-list post by a do-not-wish-to-register urllib user.
import urllib.request opener = urllib.request.build_opener() request = urllib.request.Request("http://example.com/", headers = {"Content-Type": "application/x-www-form-urlencoded"}) print(request.data, '\n', request.header_items())
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())
None [('Content-type', 'application/x-www-form-urlencoded')] b'1' [('Content-length', '1'), ('Host', 'example.com'), ('User-agent', 'Python-urllib/3.3'), ('Content-type', 'application/x-www-form-urlencoded')] b'123456789' [('Content-length', '1'), ('Host', 'example.com'), ('User-agent', 'Python-urllib/3.3'), ('Content-type', 'application/x-www-form-urlencoded')]
The first opener.open adds data and several headers to request, including content-length. The second changes the data but not the content-length. The docs do not say anything about this either way.
This is special case for more "general" problem. When request is executed with HTTP client and data is not None, it calculates content length and adds special header to request. Then one can change request.data attribute value, but header "Content-length" is not changed in this case.
Patch is attached.
I implemented request.data as property and added method "remove_header" to deal problem. Test cases are also provided.