gh-100985: Consistently wrap IPv6 IP address during CONNECT (GH-100986)

Update _get_hostport to always remove square brackets
from IPv6 addresses. Then add them if needed
in "CONNECT .." and "Host: ".
This commit is contained in:
Derek Higgins 2024-02-17 10:10:12 +00:00 committed by GitHub
parent 4dff48d1f4
commit 465db27cb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 5 deletions

View file

@ -944,9 +944,15 @@ class HTTPConnection:
def set_debuglevel(self, level): def set_debuglevel(self, level):
self.debuglevel = level self.debuglevel = level
def _wrap_ipv6(self, ip):
if b':' in ip and ip[0] != b'['[0]:
return b"[" + ip + b"]"
return ip
def _tunnel(self): def _tunnel(self):
connect = b"CONNECT %s:%d %s\r\n" % ( connect = b"CONNECT %s:%d %s\r\n" % (
self._tunnel_host.encode("idna"), self._tunnel_port, self._wrap_ipv6(self._tunnel_host.encode("idna")),
self._tunnel_port,
self._http_vsn_str.encode("ascii")) self._http_vsn_str.encode("ascii"))
headers = [connect] headers = [connect]
for header, value in self._tunnel_headers.items(): for header, value in self._tunnel_headers.items():
@ -1221,9 +1227,8 @@ class HTTPConnection:
# As per RFC 273, IPv6 address should be wrapped with [] # As per RFC 273, IPv6 address should be wrapped with []
# when used as Host header # when used as Host header
host_enc = self._wrap_ipv6(host_enc)
if ":" in host: if ":" in host:
host_enc = b'[' + host_enc + b']'
host_enc = _strip_ipv6_iface(host_enc) host_enc = _strip_ipv6_iface(host_enc)
if port == self.default_port: if port == self.default_port:

View file

@ -2408,6 +2408,22 @@ class TunnelTests(TestCase):
self.assertIn(b'PUT / HTTP/1.1\r\nHost: %(host)s\r\n' % d, self.assertIn(b'PUT / HTTP/1.1\r\nHost: %(host)s\r\n' % d,
self.conn.sock.data) self.conn.sock.data)
def test_connect_put_request_ipv6(self):
self.conn.set_tunnel('[1:2:3::4]', 1234)
self.conn.request('PUT', '/', '')
self.assertEqual(self.conn.sock.host, self.host)
self.assertEqual(self.conn.sock.port, client.HTTP_PORT)
self.assertIn(b'CONNECT [1:2:3::4]:1234', self.conn.sock.data)
self.assertIn(b'Host: [1:2:3::4]:1234', self.conn.sock.data)
def test_connect_put_request_ipv6_port(self):
self.conn.set_tunnel('[1:2:3::4]:1234')
self.conn.request('PUT', '/', '')
self.assertEqual(self.conn.sock.host, self.host)
self.assertEqual(self.conn.sock.port, client.HTTP_PORT)
self.assertIn(b'CONNECT [1:2:3::4]:1234', self.conn.sock.data)
self.assertIn(b'Host: [1:2:3::4]:1234', self.conn.sock.data)
def test_tunnel_debuglog(self): def test_tunnel_debuglog(self):
expected_header = 'X-Dummy: 1' expected_header = 'X-Dummy: 1'
response_text = 'HTTP/1.0 200 OK\r\n{}\r\n\r\n'.format(expected_header) response_text = 'HTTP/1.0 200 OK\r\n{}\r\n\r\n'.format(expected_header)

View file

@ -756,6 +756,7 @@ Raymond Hettinger
Lisa Hewus Fresh Lisa Hewus Fresh
Kevan Heydon Kevan Heydon
Wouter van Heyst Wouter van Heyst
Derek Higgins
Kelsey Hightower Kelsey Hightower
Jason Hildebrand Jason Hildebrand
Ryan Hileman Ryan Hileman

View file

@ -0,0 +1,2 @@
Update HTTPSConnection to consistently wrap IPv6 Addresses when using a
proxy.