diff --git a/Lib/httplib.py b/Lib/httplib.py index 9853285a2a8..19bcd1b41bb 100644 --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -715,7 +715,10 @@ class HTTPConnection: try: port = int(host[i+1:]) except ValueError: - raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) + if host[i+1:] == "": # http://foo.com:/ == http://foo.com/ + port = self.default_port + else: + raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) host = host[:i] else: port = self.default_port diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 2708728e801..dbc1c7f492a 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -152,13 +152,15 @@ class BasicTest(TestCase): def test_host_port(self): # Check invalid host_port - for hp in ("www.python.org:abc", "www.python.org:"): + # Note that httplib does not accept user:password@ in the host-port. + for hp in ("www.python.org:abc", "user:password@www.python.org"): self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp) for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000), ("www.python.org:80", "www.python.org", 80), ("www.python.org", "www.python.org", 80), + ("www.python.org:", "www.python.org", 80), ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)): http = httplib.HTTP(hp) c = http._conn @@ -439,6 +441,27 @@ class HTTPSTimeoutTest(TestCase): h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) self.assertEqual(h.timeout, 30) + def test_host_port(self): + # Check invalid host_port + + # Note that httplib does not accept user:password@ in the host-port. + for hp in ("www.python.org:abc", "user:password@www.python.org"): + self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp) + + for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", + 8000), + ("pypi.python.org:443", "pypi.python.org", 443), + ("pypi.python.org", "pypi.python.org", 443), + ("pypi.python.org:", "pypi.python.org", 443), + ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)): + http = httplib.HTTPS(hp) + c = http._conn + if h != c.host: + self.fail("Host incorrectly parsed: %s != %s" % (h, c.host)) + if p != c.port: + self.fail("Port incorrectly parsed: %s != %s" % (p, c.host)) + + def test_main(verbose=None): test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, HTTPSTimeoutTest, SourceAddressTest) diff --git a/Misc/NEWS b/Misc/NEWS index a4c464fe5b7..03bbf054e49 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -54,6 +54,9 @@ Core and Builtins the following case: sys.stdin.read() stopped with CTRL+d (end of file), raw_input() interrupted by CTRL+c. +- Issue #10860: httplib now correctly handles an empty port after port + delimiter in URLs. + - dict_proxy objects now display their contents rather than just the class name.