Repository: encode/httpx

Issue:
Allow `proxies` in `httpx.request()` high-level API
Spun up from #1194 

The high-level API functions such as `httpx.get()` and `httpx.post()` don't allow passing `proxies=...` yet (only possible on `Client`), but Requests does support this: https://requests.readthedocs.io/en/master/user/advanced/#proxies

We should add support for this argument:

```pycon
>>> import httpx
>>> proxies = "http://localhost:8899"
>>> r = httpx.get("https://example.com", proxies=proxies)
```

We may need to update some documentation (for example, the [HTTP Proxying](https://www.python-httpx.org/advanced/#http-proxying) docs *may* need to clarify that `proxies` does not _require_ using clients), but we can treat that as a follow-up if it's unclear what should be updated exactly.


Discussion:
Right, we may also want a note in the requests compat. section, because `Session.request(...)` allows a `proxies=...` argument, whereas `Client.request(...)` does not.

(Which is because of the knock on implications of our tighter Transport API vs. `requests` adapters.)

Resolving patch:
diff --git a/httpx/_api.py b/httpx/_api.py
--- a/httpx/_api.py
+++ b/httpx/_api.py
@@ -8,6 +8,7 @@
     CertTypes,
     CookieTypes,
     HeaderTypes,
+    ProxiesTypes,
     QueryParamTypes,
     RequestData,
     RequestFiles,
@@ -28,6 +29,7 @@ def request(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
     allow_redirects: bool = True,
     verify: VerifyTypes = True,
@@ -56,6 +58,7 @@ def request(
     request.
     * **auth** - *(optional)* An authentication class to use when sending the
     request.
+    * **proxies** - *(optional)* A dictionary mapping proxy keys to proxy URLs.
     * **timeout** - *(optional)* The timeout configuration to use when sending
     the request.
     * **allow_redirects** - *(optional)* Enables or disables HTTP redirects.
@@ -81,7 +84,7 @@ def request(
     ```
     """
     with Client(
-        cert=cert, verify=verify, timeout=timeout, trust_env=trust_env,
+        proxies=proxies, cert=cert, verify=verify, timeout=timeout, trust_env=trust_env,
     ) as client:
         return client.request(
             method=method,
@@ -108,13 +111,14 @@ def stream(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
     allow_redirects: bool = True,
     verify: VerifyTypes = True,
     cert: CertTypes = None,
     trust_env: bool = True,
 ) -> StreamContextManager:
-    client = Client(cert=cert, verify=verify, trust_env=trust_env)
+    client = Client(proxies=proxies, cert=cert, verify=verify, trust_env=trust_env)
     request = Request(
         method=method,
         url=url,
@@ -142,6 +146,7 @@ def get(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -163,6 +168,7 @@ def get(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -178,6 +184,7 @@ def options(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -199,6 +206,7 @@ def options(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -214,6 +222,7 @@ def head(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -237,6 +246,7 @@ def head(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -255,6 +265,7 @@ def post(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -276,6 +287,7 @@ def post(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -294,6 +306,7 @@ def put(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -315,6 +328,7 @@ def put(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -333,6 +347,7 @@ def patch(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -354,6 +369,7 @@ def patch(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
@@ -369,6 +385,7 @@ def delete(
     headers: HeaderTypes = None,
     cookies: CookieTypes = None,
     auth: AuthTypes = None,
+    proxies: ProxiesTypes = None,
     allow_redirects: bool = True,
     cert: CertTypes = None,
     verify: VerifyTypes = True,
@@ -390,6 +407,7 @@ def delete(
         headers=headers,
         cookies=cookies,
         auth=auth,
+        proxies=proxies,
         allow_redirects=allow_redirects,
         cert=cert,
         verify=verify,
diff --git a/httpx/_client.py b/httpx/_client.py
--- a/httpx/_client.py
+++ b/httpx/_client.py
@@ -467,7 +467,7 @@ class Client(BaseClient):
     to authenticate the client. Either a path to an SSL certificate file, or
     two-tuple of (certificate file, key file), or a three-tuple of (certificate
     file, key file, password).
-    * **proxies** - *(optional)* A dictionary mapping HTTP protocols to proxy
+    * **proxies** - *(optional)* A dictionary mapping proxy keys to proxy
     URLs.
     * **timeout** - *(optional)* The timeout configuration to use when sending
     requests.


Test patch: