]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Raise an exception in DigestAuth if non-replayable request is passed (#685)
authorKousik Mitra <kousikmitra12@gmail.com>
Sat, 4 Jan 2020 09:00:34 +0000 (14:30 +0530)
committerFlorimond Manca <florimond.manca@gmail.com>
Sat, 4 Jan 2020 09:00:34 +0000 (10:00 +0100)
* DigestAuth will raise exception if non-replayble request is passed #670

* Added new exception RequestBodyUnavailble exception to raise non replayable request error #670

* Changed RedirectBodyUnavailable exception to RequestBodyUnavailble to raise non-replayable exception #670

* fixed class declaration

* Added RequestBodyUnavailable exception. Imported it in module level

* Added RequestBodyUnavailable in the module list

* Code reformat

* Added Test to check if exception is raising if non-replayble request body is passed to DigestAuth #670

httpx/auth.py
tests/client/test_auth.py

index e0ef50c3a0b8dcadad8fae943ea7a3447fdc44b7..e412c5707fb0cb75bbbe32006b451b2daf3387e2 100644 (file)
@@ -6,7 +6,7 @@ import typing
 from base64 import b64encode
 from urllib.request import parse_http_list
 
-from .exceptions import ProtocolError
+from .exceptions import ProtocolError, RequestBodyUnavailable
 from .models import Request, Response
 from .utils import to_bytes, to_str, unquote
 
@@ -104,6 +104,8 @@ class DigestAuth(Auth):
         self.password = to_bytes(password)
 
     def __call__(self, request: Request) -> AuthFlow:
+        if not request.stream.can_replay():
+            raise RequestBodyUnavailable("Request body is no longer available.")
         response = yield request
 
         if response.status_code != 401 or "www-authenticate" not in response.headers:
index ea6ff8acac860741e49f260c4fe40f368cefa647..34ec77eb4b3750c364ee1eb0f27bae14bfc49095 100644 (file)
@@ -5,7 +5,15 @@ import typing
 
 import pytest
 
-from httpx import URL, AsyncClient, DigestAuth, ProtocolError, Request, Response
+from httpx import (
+    URL,
+    AsyncClient,
+    DigestAuth,
+    ProtocolError,
+    Request,
+    RequestBodyUnavailable,
+    Response,
+)
 from httpx.auth import Auth, AuthFlow
 from httpx.config import CertTypes, TimeoutTypes, VerifyTypes
 from httpx.dispatch.base import Dispatcher
@@ -442,3 +450,16 @@ async def test_auth_history() -> None:
     assert resp2.history == [resp1]
 
     assert len(resp1.history) == 0
+
+
+@pytest.mark.asyncio
+async def test_digest_auth_unavailable_streaming_body():
+    url = "https://example.org/"
+    auth = DigestAuth(username="tomchristie", password="password123")
+    client = AsyncClient(dispatch=MockDispatch())
+
+    async def streaming_body():
+        yield b"Example request body"
+
+    with pytest.raises(RequestBodyUnavailable):
+        await client.post(url, data=streaming_body(), auth=auth)