diff --git a/lib/core/common.py b/lib/core/common.py index 3a99cc794b4..0195ff821fe 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -5138,12 +5138,12 @@ def getHostHeader(url): retVal = url if url: - retVal = _urllib.parse.urlparse(url).netloc + parsed = _urllib.parse.urlparse(url) + retVal = parsed.netloc + defaultPort = {"http": 80, "https": 443}.get(parsed.scheme.lower()) - # Note: netloc keeps the IPv6 brackets (and any port), so only the default ports are - # stripped here - mirroring the hostname/IPv4 branch and preserving non-default ports - # (e.g. '[::1]:8080') as required by RFC 7230 - if any(retVal.endswith(':%d' % _) for _ in (80, 443)): + # Keep non-default ports, including 80 on HTTPS and 443 on HTTP. + if defaultPort is not None and retVal.endswith(':%d' % defaultPort): retVal = retVal[:retVal.rfind(':')] if retVal and retVal.count(':') > 1 and not any(_ in retVal for _ in ('[', ']')): diff --git a/tests/test_common_helpers.py b/tests/test_common_helpers.py index ca37d14bd63..6c9e88275c3 100644 --- a/tests/test_common_helpers.py +++ b/tests/test_common_helpers.py @@ -70,6 +70,21 @@ def test_with_port(self): def test_without_port(self): self.assertEqual(getHostHeader("http://example.com/path"), "example.com") + def test_default_ports_depend_on_scheme(self): + cases = ( + ("http://example.com:80/path", "example.com"), + ("https://example.com:443/path", "example.com"), + ("http://example.com:443/path", "example.com:443"), + ("https://example.com:80/path", "example.com:80"), + ("HTTP://example.com:443/path", "example.com:443"), + ("http://[::1]:80/path", "[::1]"), + ("https://[::1]:443/path", "[::1]"), + ("http://[::1]:443/path", "[::1]:443"), + ("https://[::1]:80/path", "[::1]:80"), + ) + for url, expected in cases: + self.assertEqual(getHostHeader(url), expected, msg=url) + if __name__ == "__main__": unittest.main(verbosity=2)