[issue28539] httplib/http.client HTTPConnection._get_hostport() regression
New submission from Charles Stephens: Back through the mists of time, there was a change to strip square brackets IPv6 address host literals in HTTPConnection._get_hostport(): https://hg.python.org/cpython/diff/433606e9546c/Lib/httplib.py However, the code mixed tabs and spaces and was "corected" by: https://hg.python.org/cpython/diff/9e2b94a3b5dc/Lib/httplib.py However, the intent was changed in the second diff and brackets won't be stripped. This causes problems when IPv6 address URL's are used with the requests package: In [1]: import httplib In [2]: con = httplib.HTTPConnection('[fe80::26a9:37ff:fe00:f764%eth0]', 15482) In [3]: con.request("GET", "/api/api-version") --- gaierror Traceback (most recent call last) in () > 1 con.request("GET", "/api/api-version") /usr/lib/python2.7/httplib.pyc in request(self, method, url, body, headers) 977 def request(self, method, url, body=None, headers={}): 978 """Send a complete request to the server.""" --> 979 self._send_request(method, url, body, headers) 980 981 def _set_content_length(self, body): /usr/lib/python2.7/httplib.pyc in _send_request(self, method, url, body, headers) 1011 for hdr, value in headers.iteritems(): 1012 self.putheader(hdr, value) -> 1013 self.endheaders(body) 1014 1015 def getresponse(self, buffering=False): /usr/lib/python2.7/httplib.pyc in endheaders(self, message_body) 973 else: 974 raise CannotSendHeader() --> 975 self._send_output(message_body) 976 977 def request(self, method, url, body=None, headers={}): /usr/lib/python2.7/httplib.pyc in _send_output(self, message_body) 833 msg += message_body 834 message_body = None --> 835 self.send(msg) 836 if message_body is not None: 837 #message_body was not a string (i.e. it is a file) and /usr/lib/python2.7/httplib.pyc in send(self, data) 795 if self.sock is None: 796 if self.auto_open: --> 797 self.connect() 798 else: 799 raise NotConnected() /usr/lib/python2.7/httplib.pyc in connect(self) 776 """Connect to the host and port specified in __init__.""" 777 self.sock = socket.create_connection((self.host,self.port), --> 778 self.timeout, self.source_address) 779 780 if self._tunnel_host: /usr/lib/python2.7/socket.pyc in create_connection(address, timeout, source_address) 551 host, port = address 552 err = None --> 553 for res in getaddrinfo(host, port, 0, SOCK_STREAM): 554 af, socktype, proto, canonname, sa = res 555 sock = None gaierror: [Errno -2] Name or service not known -- components: Library (Lib) files: get_hostport.diff keywords: patch messages: 279509 nosy: cfs-pure priority: normal severity: normal status: open title: httplib/http.client HTTPConnection._get_hostport() regression versions: Python 2.7, Python 3.3, Python 3.4, Python 3.5, Python 3.6, Python 3.7 Added file: http://bugs.python.org/file45233/get_hostport.diff ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: Er, that is HTTPConnection._set_hostport() not _get_hostport() -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Changes by Charles Stephens : -- title: httplib/http.client HTTPConnection._get_hostport() regression -> httplib/http.client HTTPConnection._set_hostport() regression ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: I misapplied the term 'regression'. My intent was to describe how original author's change revision 433606e9546c was refactored to make it perform incorrectly. Without the scope specifier, the outcome is the same when HTTPConnection is instantiated. When both the host and port arguments are specified, the square brackets are not stripped and are stored in the host attribute. When the port number is part of the host argument and the port argument is None, the host attribute does not include the square brackets. Examples: Python 2.7.10 (default, Jul 30 2016, 18:31:42) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import httplib >>> con1 = httplib.HTTPConnection('[fe80::26a9:37ff:fe00:f764]', 15482) >>> con1.host, con1.port ('[fe80::26a9:37ff:fe00:f764]', 15482) >>> con2 = httplib.HTTPConnection('[fe80::26a9:37ff:fe00:f764]:15482') >>> con2.host, con2.port ('fe80::26a9:37ff:fe00:f764', 15482) Compare with IPv4 behavior: >>> con3 = httplib.HTTPConnection('127.0.0.1', 15482) >>> con3.host, con3.port ('127.0.0.1', 15482) >>> con4 = httplib.HTTPConnection('127.0.0.1:15482') >>> con4.host, con4.port ('127.0.0.1', 15482) Calls to con1.request() will fail in socket.py because getaddrinfo will choke on the square brackets. Which makes sense since HTTPConnection.host is passed on down the stack as-is until it reaches create_connection() in socket.py. Moving the indent of that if block up one level makes con1 identical to con2. -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: Example with patch applied: Python 2.7.6 (default, Oct 26 2016, 20:33:50) [GCC 4.8.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import httplib >>> con1 = httplib.HTTPConnection('[fe80::26a9:37ff:fe00:f764]', 15482) >>> con1.host, con1.port ('fe80::26a9:37ff:fe00:f764', 15482) -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: Our internal use case is happening through requests via urllib3 for parsing. Essentially requests is taking the URL, passing it to urllib3 for parsing. urllib3 is returning a namedtuple of type Url which includes a host and port property which is being fed to httplib. Essentially: >>> import urllib3 >>> import httplib >>> orig_url = 'http://[2620:125:9014:3240:14:240:128:0]:8080/api/python' >>> u1 = urllib3.util.parse_url(orig_url) >>> u1 Url(scheme='http', auth=None, host='[2620:125:9014:3240:14:240:128:0]', port=8080, path='/api/python', query=None, fragment=None) >>> c1 = httplib.HTTPConnection(u1.host, port=u1.port) >>> c1.host, c1.port ('[2620:125:9014:3240:14:240:128:0]', 8080) >>> c1.request('GET', '/api/json') Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.7/httplib.py", line 979, in request self._send_request(method, url, body, headers) File "/usr/lib/python2.7/httplib.py", line 1013, in _send_request self.endheaders(body) File "/usr/lib/python2.7/httplib.py", line 975, in endheaders self._send_output(message_body) File "/usr/lib/python2.7/httplib.py", line 835, in _send_output self.send(msg) File "/usr/lib/python2.7/httplib.py", line 797, in send self.connect() File "/usr/lib/python2.7/httplib.py", line 778, in connect self.timeout, self.source_address) File "/usr/lib/python2.7/socket.py", line 553, in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): socket.gaierror: [Errno -2] Name or service not known -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: Not when passing it to getaddrinfo(). -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28539] httplib/http.client HTTPConnection._set_hostport() regression
Charles Stephens added the comment: Yes, I'm working on patching urllib3 to preprocess the host argument to HTTPConnection. However, it makes sense to strip square brackets regardless. -- ___ Python tracker <http://bugs.python.org/issue28539> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com