]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Deprecate per-request cookies (#1574)
authorTom Christie <tom@tomchristie.com>
Mon, 19 Apr 2021 10:18:32 +0000 (11:18 +0100)
committerGitHub <noreply@github.com>
Mon, 19 Apr 2021 10:18:32 +0000 (11:18 +0100)
* Deprecate per-request cookies

* Update docs/compatibility.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
* Update httpx/_client.py

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
* Update compatibility.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
docs/compatibility.md
httpx/_api.py
httpx/_client.py
tests/client/test_cookies.py

index c330c15d222b09fcd58fad4a12ed5a989d7c36c8..7aed9dc1ed3ec683d577479579991f6d3cbccdaa 100644 (file)
@@ -37,6 +37,26 @@ HTTPX uses `utf-8` for encoding `str` request bodies. For example, when using `c
 
 For response bodies, assuming the server didn't send an explicit encoding then HTTPX will do its best to figure out an appropriate encoding. Unlike Requests which uses the `chardet` library, HTTPX relies on a plainer fallback strategy (basically attempting UTF-8, or using Windows-1252 as a fallback). This strategy should be robust enough to handle the vast majority of use cases.
 
+## Cookies
+
+If using a client instance, then cookies should always be set on the client rather than on a per-request basis.
+
+This usage is supported:
+
+```python
+client = httpx.Client(cookies=...)
+client.post(...)
+```
+
+This usage is **not** supported:
+
+```python
+client = httpx.Client()
+client.post(..., cookies=...)
+```
+
+We prefer enforcing a stricter API here because it provides clearer expectations around cookie persistence, particularly when redirects occur.
+
 ## Status Codes
 
 In our documentation we prefer the uppercased versions, such as `codes.NOT_FOUND`, but also provide lower-cased versions for API compatibility with `requests`.
index 51bc246aa30d1821e807d33d0f1a01fe0eb18631..ff40ce65e128079df9f6499655613715cb1df868 100644 (file)
@@ -90,7 +90,12 @@ def request(
     ```
     """
     with Client(
-        proxies=proxies, cert=cert, verify=verify, timeout=timeout, trust_env=trust_env
+        cookies=cookies,
+        proxies=proxies,
+        cert=cert,
+        verify=verify,
+        timeout=timeout,
+        trust_env=trust_env,
     ) as client:
         return client.request(
             method=method,
@@ -101,7 +106,6 @@ def request(
             json=json,
             params=params,
             headers=headers,
-            cookies=cookies,
             auth=auth,
             allow_redirects=allow_redirects,
         )
@@ -138,7 +142,7 @@ def stream(
     [0]: /quickstart#streaming-responses
     """
     with Client(
-        proxies=proxies, cert=cert, verify=verify, trust_env=trust_env
+        cookies=cookies, proxies=proxies, cert=cert, verify=verify, trust_env=trust_env
     ) as client:
         with client.stream(
             method=method,
@@ -149,7 +153,6 @@ def stream(
             json=json,
             params=params,
             headers=headers,
-            cookies=cookies,
             auth=auth,
             allow_redirects=allow_redirects,
         ) as response:
index d0ed0893a10ee077f7df61c7215f648102277f1f..c5e1f1f223299b9ccfe57d5575e669a98cc53960 100644 (file)
@@ -735,6 +735,14 @@ class Client(BaseClient):
 
         [0]: /advanced/#merging-of-configuration
         """
+        if cookies is not None:
+            message = (
+                "Setting per-request cookies=<...> is being deprecated, because "
+                "the expected behaviour on cookie persistence is ambiguous. Set "
+                "cookies directly on the client instance instead."
+            )
+            warnings.warn(message, DeprecationWarning)
+
         request = self.build_request(
             method=method,
             url=url,
index fe9125fa062118b857187d58b9d337af71e149e2..f0c8352593795d2e048e75dd1e697979cab6f146 100644 (file)
@@ -1,5 +1,7 @@
 from http.cookiejar import Cookie, CookieJar
 
+import pytest
+
 import httpx
 
 
@@ -20,8 +22,25 @@ def test_set_cookie() -> None:
     url = "http://example.org/echo_cookies"
     cookies = {"example-name": "example-value"}
 
+    client = httpx.Client(
+        cookies=cookies, transport=httpx.MockTransport(get_and_set_cookies)
+    )
+    response = client.get(url)
+
+    assert response.status_code == 200
+    assert response.json() == {"cookies": "example-name=example-value"}
+
+
+def test_set_per_request_cookie_is_deprecated() -> None:
+    """
+    Sending a request including a per-request cookie is deprecated.
+    """
+    url = "http://example.org/echo_cookies"
+    cookies = {"example-name": "example-value"}
+
     client = httpx.Client(transport=httpx.MockTransport(get_and_set_cookies))
-    response = client.get(url, cookies=cookies)
+    with pytest.warns(DeprecationWarning):
+        response = client.get(url, cookies=cookies)
 
     assert response.status_code == 200
     assert response.json() == {"cookies": "example-name=example-value"}
@@ -55,8 +74,10 @@ def test_set_cookie_with_cookiejar() -> None:
     )
     cookies.set_cookie(cookie)
 
-    client = httpx.Client(transport=httpx.MockTransport(get_and_set_cookies))
-    response = client.get(url, cookies=cookies)
+    client = httpx.Client(
+        cookies=cookies, transport=httpx.MockTransport(get_and_set_cookies)
+    )
+    response = client.get(url)
 
     assert response.status_code == 200
     assert response.json() == {"cookies": "example-name=example-value"}
@@ -90,8 +111,9 @@ def test_setting_client_cookies_to_cookiejar() -> None:
     )
     cookies.set_cookie(cookie)
 
-    client = httpx.Client(transport=httpx.MockTransport(get_and_set_cookies))
-    client.cookies = cookies  # type: ignore
+    client = httpx.Client(
+        cookies=cookies, transport=httpx.MockTransport(get_and_set_cookies)
+    )
     response = client.get(url)
 
     assert response.status_code == 200
@@ -108,7 +130,8 @@ def test_set_cookie_with_cookies_model() -> None:
     cookies["example-name"] = "example-value"
 
     client = httpx.Client(transport=httpx.MockTransport(get_and_set_cookies))
-    response = client.get(url, cookies=cookies)
+    client.cookies = cookies
+    response = client.get(url)
 
     assert response.status_code == 200
     assert response.json() == {"cookies": "example-name=example-value"}