Skip to content

Do we flush the decoder when reaching EOF in partial reads? #2799

Description

@pquentin

I started writing a very detailed bug report and then convinced me that it was not real. Sorry, this will be the short version now. Looks at our flush_decoder logic:

flush_decoder = False
fp_closed = getattr(self._fp, "closed", False)
with self._error_catcher():
data = self._fp_read(amt) if not fp_closed else b""
if amt is None:
flush_decoder = True
else:
cache_content = False
if (
amt != 0 and not data
): # Platform-specific: Buggy versions of Python.
# Close the connection when no data is returned
#
# This is redundant to what httplib/http.client _should_
# already do. However, versions of python released before
# December 15, 2012 (http://bugs.python.org/issue16298) do
# not properly close the connection in all cases. There is
# no harm in redundantly calling close.
self._fp.close()
flush_decoder = True
if (
self.enforce_content_length
and self.length_remaining is not None
and self.length_remaining != 0
):
# This is an edge case that httplib failed to cover due
# to concerns of backward compatibility. We're
# addressing it here to make sure IncompleteRead is
# raised during streaming, so all calls with incorrect
# Content-Length are caught.
raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
if data:
self._fp_bytes_read += len(data)
if self.length_remaining is not None:
self.length_remaining -= len(data)
data = self._decode(data, decode_content, flush_decoder)

We should only flush when there is no data left. In the streaming case, it would be because we reached EOF, and data is b''. Which is done correctly line 776. But then we don't call self._decode because if data will prevent us from doing it. So we don't flush().

This bug was introduced in urllib3 1.11, released in July 2015: 29e144f. Surely in 7 years someone would have noticed if they had missing data.

So surely the flush() call is not actually doing anything, whatever the reason is.

Metadata

Metadata

Assignees

No one assigned

    Labels

    💰 Bounty $300If you complete this issue we'll pay you $300 on OpenCollective!

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions