]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
URL.port becomes Optional[int] (#1080)
authorTom Christie <tom@tomchristie.com>
Fri, 24 Jul 2020 10:42:13 +0000 (11:42 +0100)
committerGitHub <noreply@github.com>
Fri, 24 Jul 2020 10:42:13 +0000 (11:42 +0100)
* URL.port becomes Optional[int], not int

* Minor _transport_for_url refactor

* Add docstring

httpx/_client.py
httpx/_models.py
httpx/_utils.py
tests/client/test_proxies.py
tests/client/test_redirects.py
tests/models/test_requests.py
tests/models/test_url.py
tests/test_config.py

index e7d018bb44588c06563fe8677bdcbcd940aa6b21..6aa576fe8a9f6d735e643e07f81382a1c60f2565 100644 (file)
@@ -543,10 +543,10 @@ class Client(BaseClient):
         enforce_http_url(url)
 
         if self._proxies and not should_not_be_proxied(url):
-            is_default_port = (url.scheme == "http" and url.port == 80) or (
-                url.scheme == "https" and url.port == 443
-            )
-            hostname = f"{url.host}:{url.port}"
+            default_port = {"http": 80, "https": 443}[url.scheme]
+            is_default_port = url.port is None or url.port == default_port
+            port = url.port or default_port
+            hostname = f"{url.host}:{port}"
             proxy_keys = (
                 f"{url.scheme}://{hostname}",
                 f"{url.scheme}://{url.host}" if is_default_port else None,
@@ -1076,10 +1076,10 @@ class AsyncClient(BaseClient):
         enforce_http_url(url)
 
         if self._proxies and not should_not_be_proxied(url):
-            is_default_port = (url.scheme == "http" and url.port == 80) or (
-                url.scheme == "https" and url.port == 443
-            )
-            hostname = f"{url.host}:{url.port}"
+            default_port = {"http": 80, "https": 443}[url.scheme]
+            is_default_port = url.port is None or url.port == default_port
+            port = url.port or default_port
+            hostname = f"{url.host}:{port}"
             proxy_keys = (
                 f"{url.scheme}://{hostname}",
                 f"{url.scheme}://{url.host}" if is_default_port else None,
index 73db360d4c2b5c100d8581a71387557570521222..785bf4721370907bd872281f9c085d09ea82693a 100644 (file)
@@ -105,11 +105,9 @@ class URL:
         return self._uri_reference.host or ""
 
     @property
-    def port(self) -> int:
+    def port(self) -> typing.Optional[int]:
         port = self._uri_reference.port
-        if port is None:
-            return {"https": 443, "http": 80}[self.scheme]
-        return int(port)
+        return int(port) if port else None
 
     @property
     def path(self) -> str:
@@ -131,7 +129,7 @@ class URL:
         return self._uri_reference.fragment or ""
 
     @property
-    def raw(self) -> typing.Tuple[bytes, bytes, int, bytes]:
+    def raw(self) -> typing.Tuple[bytes, bytes, typing.Optional[int], bytes]:
         return (
             self.scheme.encode("ascii"),
             self.host.encode("ascii"),
@@ -167,7 +165,7 @@ class URL:
             or "port" in kwargs
         ):
             host = kwargs.pop("host", self.host)
-            port = kwargs.pop("port", None if self.is_relative_url else self.port)
+            port = kwargs.pop("port", self.port)
             username = kwargs.pop("username", self.username)
             password = kwargs.pop("password", self.password)
 
index b43f38ee31bc561d35d99dd8f4558aa0ec13d64d..55503655d32df4aa9694bf6704caa8e4c65b16dc 100644 (file)
@@ -273,12 +273,20 @@ def enforce_http_url(url: "URL") -> None:
         raise InvalidURL('URL scheme must be "http" or "https".')
 
 
+def port_or_default(url: "URL") -> typing.Optional[int]:
+    if url.port is not None:
+        return url.port
+    return {"http": 80, "https": 443}.get(url.scheme)
+
+
 def same_origin(url: "URL", other: "URL") -> bool:
     """
     Return 'True' if the given URLs share the same origin.
     """
     return (
-        url.scheme == other.scheme and url.host == other.host and url.port == other.port
+        url.scheme == other.scheme
+        and url.host == other.host
+        and port_or_default(url) == port_or_default(other)
     )
 
 
index f981948839eebd856725e74e88c47e1ee9712f9d..f5af90cc81d9915bb77b0466e7c740cc632930dc 100644 (file)
@@ -4,6 +4,18 @@ import pytest
 import httpx
 
 
+def url_to_origin(url: str):
+    """
+    Given a URL string, return the origin in the raw tuple format that
+    `httpcore` uses for it's representation.
+    """
+    DEFAULT_PORTS = {b"http": 80, b"https": 443}
+    scheme, host, explicit_port = httpx.URL(url).raw[:3]
+    default_port = DEFAULT_PORTS[scheme]
+    port = default_port if explicit_port is None else explicit_port
+    return scheme, host, port
+
+
 @pytest.mark.parametrize(
     ["proxies", "expected_proxies"],
     [
@@ -27,7 +39,7 @@ def test_proxies_parameter(proxies, expected_proxies):
         assert proxy_key in client._proxies
         proxy = client._proxies[proxy_key]
         assert isinstance(proxy, httpcore.AsyncHTTPProxy)
-        assert proxy.proxy_origin == httpx.URL(url).raw[:3]
+        assert proxy.proxy_origin == url_to_origin(url)
 
     assert len(expected_proxies) == len(client._proxies)
 
@@ -85,7 +97,7 @@ def test_transport_for_request(url, proxies, expected):
         assert transport is client._transport
     else:
         assert isinstance(transport, httpcore.AsyncHTTPProxy)
-        assert transport.proxy_origin == httpx.URL(expected).raw[:3]
+        assert transport.proxy_origin == url_to_origin(expected)
 
 
 @pytest.mark.asyncio
@@ -131,4 +143,4 @@ def test_proxies_environ(monkeypatch, client_class, url, env, expected):
     if expected is None:
         assert transport == client._transport
     else:
-        assert transport.proxy_origin == httpx.URL(expected).raw[:3]
+        assert transport.proxy_origin == url_to_origin(expected)
index 30b6f6a128c37352c0fb628c8c786ac7b7ddc97c..61e600cbb006ee65f40aaa81744bcf91e7b6264a 100644 (file)
@@ -242,7 +242,7 @@ async def test_malformed_redirect():
     client = AsyncClient(transport=AsyncMockTransport())
     response = await client.get("http://example.org/malformed_redirect")
     assert response.status_code == codes.OK
-    assert response.url == URL("https://example.org/")
+    assert response.url == URL("https://example.org:443/")
     assert len(response.history) == 1
 
 
index 7fd61a15a4c081b8d537580defa0be5be32fd6d9..e360ea052582d1381936b2b83b547afc77058004 100644 (file)
@@ -102,11 +102,11 @@ def test_url():
     url = "http://example.org"
     request = httpx.Request("GET", url)
     assert request.url.scheme == "http"
-    assert request.url.port == 80
+    assert request.url.port is None
     assert request.url.full_path == "/"
 
     url = "https://example.org/abc?foo=bar"
     request = httpx.Request("GET", url)
     assert request.url.scheme == "https"
-    assert request.url.port == 443
+    assert request.url.port is None
     assert request.url.full_path == "/abc?foo=bar"
index daa84e0ac559d3c439fa0faf28a33d845ddaab49..6c0fdac82b01c70c45f656336fc21fb1ff19c668 100644 (file)
@@ -18,9 +18,9 @@ from httpx import URL
             "http://xn--knigsgchen-b4a3dun.de",
             "xn--knigsgchen-b4a3dun.de",
             "http",
-            80,
+            None,
         ),
-        ("https://faß.de", "https://xn--fa-hia.de", "xn--fa-hia.de", "https", 443),
+        ("https://faß.de", "https://xn--fa-hia.de", "xn--fa-hia.de", "https", None),
         (
             "https://βόλος.com:443",
             "https://xn--nxasmm1c.com:443",
index 46d154cdb82810746f6d3bc2198f61f20f65e02c..0c2c2f73ca28f868c650c7b0874e78a897165e7e 100644 (file)
@@ -214,7 +214,7 @@ def test_ssl_config_support_for_keylog_file(tmpdir, monkeypatch):  # pragma: noc
         ("https://example.com", "https://example.com", {}, "DEFAULT"),
         (
             "https://user:pass@example.com",
-            "https://example.com:443",
+            "https://example.com",
             {"proxy-authorization": "Basic dXNlcjpwYXNz"},
             "DEFAULT",
         ),