diff -r 45cf82f424ce Lib/http/client.py --- a/Lib/http/client.py Sun Feb 21 22:00:29 2016 +0200 +++ b/Lib/http/client.py Wed Mar 09 20:42:53 2016 +0100 @@ -638,6 +638,8 @@ """ if self.fp is None or self._method == "HEAD": return b"" + if self.length == 0: + n = 0 if self.chunked: return self._read1_chunked(n) try: @@ -650,6 +652,8 @@ result = self.fp.read1(16*1024) if not result and n: self._close_conn() + elif self.length is not None: + self.length -= len(result) return result def peek(self, n=-1): @@ -664,12 +668,16 @@ def readline(self, limit=-1): if self.fp is None or self._method == "HEAD": return b"" + if self.length == 0: + limit = 0 if self.chunked: # Fallback to IOBase readline which uses peek() and read() return super().readline(limit) result = self.fp.readline(limit) if not result and limit: self._close_conn() + elif self.length is not None: + self.length -= len(result) return result def _read1_chunked(self, n): diff -r 45cf82f424ce Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py Sun Feb 21 22:00:29 2016 +0200 +++ b/Lib/test/test_httplib.py Wed Mar 09 20:42:53 2016 +0100 @@ -355,6 +355,21 @@ resp.close() self.assertTrue(resp.closed) + def test_mixed_reads(self): + # if we have a length, the system knows when to close itself + # same behaviour than when we read the whole thing with read() + body = "HTTP/1.1 200 Ok\r\nContent-Length: 13\r\n\r\nText\r\nAnother" + sock = FakeSocket(body) + resp = client.HTTPResponse(sock) + resp.begin() + self.assertEqual(resp.readline(), b'Text\r\n') + self.assertFalse(resp.isclosed()) + self.assertEqual(resp.read(), b'Another') + self.assertTrue(resp.isclosed()) + self.assertFalse(resp.closed) + resp.close() + self.assertTrue(resp.closed) + def test_partial_readintos(self): # if we have a length, the system knows when to close itself # same behaviour than when we read the whole thing with read()