Skip to content

Commit 5451a96

Browse files
miss-islingtonbielpieroliLorenaMBorges
authored
[3.15] gh-159044: Restore string conversion for HTTP tunnel header values (GH-159216) (GH-159382)
(cherry picked from commit 8138bf1) Co-authored-by: João Gabriel Pieroli da Silva <joaogabrielpieroli18@gmail.com> Co-authored-by: LorenaMBorges <lborgescomp@gmail.com>
1 parent b3fae57 commit 5451a96

4 files changed

Lines changed: 24 additions & 2 deletions

File tree

‎Doc/library/http.client.rst‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ HTTPConnection Objects
370370
proxy server).
371371

372372
The *headers* argument should be a mapping of extra HTTP headers to send with
373-
the CONNECT request.
373+
the CONNECT request. Non-string header values are converted to strings via
374+
:func:`str`.
374375

375376
As HTTP/1.1 is used for HTTP CONNECT tunnelling request, `as per the RFC
376377
<https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.6>`_, a HTTP ``Host:``

‎Lib/http/client.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ def _tunnel(self):
10131013
headers = [connect]
10141014
for header, value in self._tunnel_headers.items():
10151015
header_bytes = header.encode("latin-1")
1016-
value_bytes = value.encode("latin-1")
1016+
value_bytes = str(value).encode("latin-1")
10171017
if not _is_legal_header_name(header_bytes):
10181018
raise ValueError('Invalid header name %r' % (header_bytes,))
10191019
if _is_illegal_header_value(value_bytes):

‎Lib/test/test_httplib.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,6 +2766,23 @@ def _create_connection(address, timeout=None, source_address=None):
27662766
self.assertIsNotNone(exc)
27672767
self.assertTrue(sock.file_closed)
27682768

2769+
def test_tunnel_nonstr_headers(self):
2770+
class CustomObject:
2771+
def __str__(self):
2772+
return 'custom-str'
2773+
2774+
self.conn.set_tunnel('destination.com', headers={
2775+
'None-Value': None,
2776+
'Integer-Value': 9,
2777+
'Custom-Value': CustomObject(),
2778+
})
2779+
2780+
self.conn.request('HEAD', '/', '')
2781+
2782+
self.assertIn(b'None-Value: None\r\n', self.conn.sock.data)
2783+
self.assertIn(b'Integer-Value: 9\r\n', self.conn.sock.data)
2784+
self.assertIn(b'Custom-Value: custom-str\r\n', self.conn.sock.data)
2785+
27692786

27702787
if __name__ == '__main__':
27712788
unittest.main(verbosity=2)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Restore the previous behaviour of :meth:`http.client.HTTPConnection.set_tunnel`
2+
where header values that are not strings (such as :const:`None`, :class:`int`
3+
or other objects) are converted with :class:`str` instead of raising
4+
:exc:`AttributeError` when the request is sent.

0 commit comments

Comments
 (0)