diff options
author | Alexey Namyotkin <62434915+nametkin@users.noreply.github.com> | 2023-05-16 06:20:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-16 06:20:30 (GMT) |
commit | 85ec192ac4b000d4e47df6123b65eacbd1fdccfa (patch) | |
tree | 6029b8cda6865e42154c9bcea0e419c8ba0f54eb /Lib/http | |
parent | 24d8b88420b81fc60aeb0cbcacef1e72d633824a (diff) | |
download | cpython-85ec192ac4b000d4e47df6123b65eacbd1fdccfa.zip cpython-85ec192ac4b000d4e47df6123b65eacbd1fdccfa.tar.gz cpython-85ec192ac4b000d4e47df6123b65eacbd1fdccfa.tar.bz2 |
gh-69152: add method get_proxy_response_headers to HTTPConnection class (#104248)
Add http.client.HTTPConnection method get_proxy_response_headers() - this is a followup to https://github.com/python/cpython/pull/26152 which added it as a non-public attribute. This way we don't pre-compute a headers dictionary that most users will never access. The new method is properly public and documented and triggers full proxy header parsing into a dict only when actually called.
---------
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
Diffstat (limited to 'Lib/http')
-rw-r--r-- | Lib/http/client.py | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/Lib/http/client.py b/Lib/http/client.py index 50f2b46..59a9fd7 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -221,8 +221,9 @@ def _read_headers(fp): break return headers -def parse_headers(fp, _class=HTTPMessage): - """Parses only RFC2822 headers from a file pointer. +def _parse_header_lines(header_lines, _class=HTTPMessage): + """ + Parses only RFC2822 headers from header lines. email Parser wants to see strings rather than bytes. But a TextIOWrapper around self.rfile would buffer too many bytes @@ -231,10 +232,15 @@ def parse_headers(fp, _class=HTTPMessage): to parse. """ - headers = _read_headers(fp) - hstring = b''.join(headers).decode('iso-8859-1') + hstring = b''.join(header_lines).decode('iso-8859-1') return email.parser.Parser(_class=_class).parsestr(hstring) +def parse_headers(fp, _class=HTTPMessage): + """Parses only RFC2822 headers from a file pointer.""" + + headers = _read_headers(fp) + return _parse_header_lines(headers, _class) + class HTTPResponse(io.BufferedIOBase): @@ -858,7 +864,7 @@ class HTTPConnection: self._tunnel_host = None self._tunnel_port = None self._tunnel_headers = {} - self._proxy_response_headers = None + self._raw_proxy_headers = None (self.host, self.port) = self._get_hostport(host, port) @@ -945,11 +951,11 @@ class HTTPConnection: try: (version, code, message) = response._read_status() - self._proxy_response_headers = parse_headers(response.fp) + self._raw_proxy_headers = _read_headers(response.fp) if self.debuglevel > 0: - for hdr, val in self._proxy_response_headers.items(): - print("header:", hdr + ":", val) + for header in self._raw_proxy_headers: + print('header:', header.decode()) if code != http.HTTPStatus.OK: self.close() @@ -958,6 +964,21 @@ class HTTPConnection: finally: response.close() + def get_proxy_response_headers(self): + """ + Returns a dictionary with the headers of the response + received from the proxy server to the CONNECT request + sent to set the tunnel. + + If the CONNECT request was not sent, the method returns + an empty dictionary. + """ + return ( + _parse_header_lines(self._raw_proxy_headers) + if self._raw_proxy_headers is not None + else {} + ) + def connect(self): """Connect to the host and port specified in __init__.""" sys.audit("http.client.connect", self, self.host, self.port) |