Content-Length is not checked, resulting in short reads with no error #4956
Description
Currently, requests does not detect when the length of a response body does not match the Content-Length
header. This behavior results in undetected failures when a TCP connection is closed early (for example) and is contrary to the behavior of other tools (e.g. curl
) and libraries (e.g. reqwest
) which fail if a body length does not match Content-Length
[3]. It is also contrary to the HTTP 1.1 RFC [5]. Frustration with this behavior is well documented ([1][2][3][4]) and was first reported as a bug 5 years ago [5]. In [1] it was agreed that the underlying checking should be done in urllib3. This was implemented in urllib3 v1.17 with the enforce_content_length
setting [6]. However the setting defaults to False. At the time this was implemented in urllib3, there was a merge on requests:proposed/3.0.0 [7] that set enforce_content_length
to True so that short reads would be detected (it was later reverted edit: it wasn't reverted), but no such merge happened on requests 2.x branch.
Requests master now requires urllib3>=1.21 so we are guaranteed to have enforce_content_length. There is a strong argument to be made that enforce_content_length=True
should be the default but at the very least it should be possible for a user to opt into this.
[1] #2833
[2] #2275
[3] https://blog.petrzemek.net/2018/04/22/on-incomplete-http-reads-and-the-requests-library-in-python/
[4] https://news.ycombinator.com/item?id=16896899
[5] #1855
[6] urllib3/urllib3#949
[7] #3563.
Expected Result
HTTP bodies that do not match the HTTP Content-Length
header should be detected
Actual Result
HTTP bodies that do not match the HTTP Content-Length
header are not detected.
Reproduction Steps
System Information
$ python -m requests.help
{
"chardet": {
"version": "3.0.4"
},
"cryptography": {
"version": ""
},
"idna": {
"version": "2.7"
},
"implementation": {
"name": "CPython",
"version": "3.7.0"
},
"platform": {
"release": "18.2.0",
"system": "Darwin"
},
"pyOpenSSL": {
"openssl_version": "",
"version": null
},
"requests": {
"version": "2.21.0"
},
"system_ssl": {
"version": "1000211f"
},
"urllib3": {
"version": "1.24"
},
"using_pyopenssl": false
}