]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Add support for no-proxy configurations (#1099)
authorTom Christie <tom@tomchristie.com>
Fri, 31 Jul 2020 09:21:11 +0000 (10:21 +0100)
committerGitHub <noreply@github.com>
Fri, 31 Jul 2020 09:21:11 +0000 (10:21 +0100)
* Add internal URLMatcher class

* Use URLMatcher for proxy lookups in transport_for_url

* Docstring

* Pin pytest

* Add support for no-proxies configurations

httpx/_client.py
httpx/_types.py
tests/client/test_proxies.py

index dca8718fcfed28cef081b5dc1e1573749af20c02..4a7fc030a0134a66773e1b8f5cb9c6c097b97efe 100644 (file)
@@ -86,7 +86,7 @@ class BaseClient:
 
     def _get_proxy_map(
         self, proxies: typing.Optional[ProxiesTypes], trust_env: bool,
-    ) -> typing.Dict[str, Proxy]:
+    ) -> typing.Dict[str, typing.Optional[Proxy]]:
         if proxies is None:
             if trust_env:
                 return {
@@ -94,15 +94,15 @@ class BaseClient:
                     for key, url in get_environment_proxies().items()
                 }
             return {}
-        elif isinstance(proxies, (str, URL, Proxy)):
-            proxy = Proxy(url=proxies) if isinstance(proxies, (str, URL)) else proxies
-            return {"all": proxy}
-        else:
+        if isinstance(proxies, dict):
             new_proxies = {}
             for key, value in proxies.items():
                 proxy = Proxy(url=value) if isinstance(value, (str, URL)) else value
                 new_proxies[str(key)] = proxy
             return new_proxies
+        else:
+            proxy = Proxy(url=proxies) if isinstance(proxies, (str, URL)) else proxies
+            return {"all": proxy}
 
     @property
     def headers(self) -> Headers:
@@ -472,8 +472,12 @@ class Client(BaseClient):
             app=app,
             trust_env=trust_env,
         )
-        self._proxies: typing.Dict[URLMatcher, httpcore.SyncHTTPTransport] = {
-            URLMatcher(key): self._init_proxy_transport(
+        self._proxies: typing.Dict[
+            URLMatcher, typing.Optional[httpcore.SyncHTTPTransport]
+        ] = {
+            URLMatcher(key): None
+            if proxy is None
+            else self._init_proxy_transport(
                 proxy,
                 verify=verify,
                 cert=cert,
@@ -543,7 +547,7 @@ class Client(BaseClient):
         if self._proxies and not should_not_be_proxied(url):
             for matcher, transport in self._proxies.items():
                 if matcher.matches(url):
-                    return transport
+                    return self._transport if transport is None else transport
 
         return self._transport
 
@@ -885,7 +889,8 @@ class Client(BaseClient):
     def close(self) -> None:
         self._transport.close()
         for proxy in self._proxies.values():
-            proxy.close()
+            if proxy is not None:
+                proxy.close()
 
     def __enter__(self) -> "Client":
         return self
@@ -989,8 +994,12 @@ class AsyncClient(BaseClient):
             app=app,
             trust_env=trust_env,
         )
-        self._proxies: typing.Dict[URLMatcher, httpcore.AsyncHTTPTransport] = {
-            URLMatcher(key): self._init_proxy_transport(
+        self._proxies: typing.Dict[
+            URLMatcher, typing.Optional[httpcore.AsyncHTTPTransport]
+        ] = {
+            URLMatcher(key): None
+            if proxy is None
+            else self._init_proxy_transport(
                 proxy,
                 verify=verify,
                 cert=cert,
@@ -1060,7 +1069,7 @@ class AsyncClient(BaseClient):
         if self._proxies and not should_not_be_proxied(url):
             for matcher, transport in self._proxies.items():
                 if matcher.matches(url):
-                    return transport
+                    return self._transport if transport is None else transport
 
         return self._transport
 
@@ -1402,7 +1411,8 @@ class AsyncClient(BaseClient):
     async def aclose(self) -> None:
         await self._transport.aclose()
         for proxy in self._proxies.values():
-            await proxy.aclose()
+            if proxy is not None:
+                await proxy.aclose()
 
     async def __aenter__(self) -> "AsyncClient":
         return self
index bfce5650dad6934f9c1c00fe8f212a2cb7d74bb0..89a90a2cf58d844c8d7ecffcb8e3b01b295060ce 100644 (file)
@@ -54,7 +54,7 @@ TimeoutTypes = Union[
     Tuple[Optional[float], Optional[float], Optional[float], Optional[float]],
     "Timeout",
 ]
-ProxiesTypes = Union[URLTypes, "Proxy", Dict[URLTypes, Union[URLTypes, "Proxy"]]]
+ProxiesTypes = Union[URLTypes, "Proxy", Dict[URLTypes, Union[None, URLTypes, "Proxy"]]]
 
 AuthTypes = Union[
     Tuple[Union[str, bytes], Union[str, bytes]],
index 6120bc1d385cd9fb3006b60b76b9468d5ebdfd06..d361372c1f30f57dc188fdf4410e88664cee6648 100644 (file)
@@ -58,6 +58,7 @@ PROXY_URL = "http://[::1]"
         ("http://example.com", {"http://example.net": PROXY_URL}, None),
         ("http://example.com:443", {"http://example.com": PROXY_URL}, PROXY_URL),
         ("http://example.com", {"all": PROXY_URL}, PROXY_URL),
+        ("http://example.com", {"all": PROXY_URL, "http://example.com": None}, None),
         ("http://example.com", {"http": PROXY_URL}, PROXY_URL),
         ("http://example.com", {"all://example.com": PROXY_URL}, PROXY_URL),
         ("http://example.com", {"all://example.com:80": PROXY_URL}, None),