From ef989ab7c29852e76dd3f5f76cc09de33f10a40b Mon Sep 17 00:00:00 2001 From: Alexey Namyotkin <62434915+nametkin@users.noreply.github.com> Date: Fri, 5 May 2023 21:52:24 +0300 Subject: [PATCH] gh-69152: Add _proxy_response_headers attribute to HTTPConnection (#26152) Add _proxy_response_headers attribute to HTTPConnection (#26152) --------- Co-authored-by: Senthil Kumaran --- Lib/http/client.py | 18 +++++++----------- Lib/test/test_httplib.py | 14 ++++++++++++++ .../2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst | 3 +++ 3 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index 74f7bcb68fb6bc..50f2b4680769c8 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -858,6 +858,7 @@ def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, self._tunnel_host = None self._tunnel_port = None self._tunnel_headers = {} + self._proxy_response_headers = None (self.host, self.port) = self._get_hostport(host, port) @@ -944,21 +945,16 @@ def _tunnel(self): try: (version, code, message) = response._read_status() + self._proxy_response_headers = parse_headers(response.fp) + + if self.debuglevel > 0: + for hdr, val in self._proxy_response_headers.items(): + print("header:", hdr + ":", val) + if code != http.HTTPStatus.OK: self.close() raise OSError(f"Tunnel connection failed: {code} {message.strip()}") - while True: - line = response.fp.readline(_MAXLINE + 1) - if len(line) > _MAXLINE: - raise LineTooLong("header line") - if not line: - # for sites which EOF without sending a trailer - break - if line in (b'\r\n', b'\n', b''): - break - if self.debuglevel > 0: - print('header:', line.decode()) finally: response.close() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 37f77fe0a320c7..4b1d355f550b49 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -2390,6 +2390,20 @@ def test_tunnel_debuglog(self): lines = output.getvalue().splitlines() self.assertIn('header: {}'.format(expected_header), lines) + def test_proxy_response_headers(self): + expected_header = ('X-Dummy', '1') + response_text = ( + 'HTTP/1.0 200 OK\r\n' + '{0}\r\n\r\n'.format(':'.join(expected_header)) + ) + + self.conn._create_connection = self._create_connection(response_text) + self.conn.set_tunnel('destination.com') + + self.conn.request('PUT', '/', '') + headers = self.conn._proxy_response_headers + self.assertIn(expected_header, headers.items()) + def test_tunnel_leak(self): sock = None diff --git a/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst b/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst new file mode 100644 index 00000000000000..ba113673b7fbe5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst @@ -0,0 +1,3 @@ +Added attribute '_proxy_response_headers' to HTTPConnection class. This +attribute contains the headers of the proxy server response to the CONNECT +request.