8
8
import os .path
9
9
from typing import Any
10
10
from collections .abc import Callable
11
-
12
11
import httpx
13
12
from httpx import AsyncClient , BasicAuth , DigestAuth
14
13
from zeep .cache import SqliteCache
27
26
from .settings import DEFAULT_SETTINGS
28
27
from .transport import ASYNC_TRANSPORT
29
28
from .types import FastDateTime , ForgivingTime
30
- from .util import create_no_verify_ssl_context , normalize_url , path_isfile , utcnow
29
+ from .util import (
30
+ create_no_verify_ssl_context ,
31
+ normalize_url ,
32
+ path_isfile ,
33
+ utcnow ,
34
+ strip_user_pass_url ,
35
+ obscure_user_pass_url ,
36
+ )
31
37
from .wrappers import retry_connection_error # noqa: F401
32
38
from .wsa import WsAddressingIfMissingPlugin
33
39
@@ -573,12 +579,16 @@ async def get_snapshot(
573
579
else :
574
580
auth = DigestAuth (self .user , self .passwd )
575
581
576
- try :
577
- response = await self ._snapshot_client .get (uri , auth = auth )
578
- except httpx .TimeoutException as error :
579
- raise ONVIFTimeoutError (f"Timed out fetching { uri } : { error } " ) from error
580
- except httpx .RequestError as error :
581
- raise ONVIFError (f"Error fetching { uri } : { error } " ) from error
582
+ response = await self ._try_snapshot_uri (uri , auth )
583
+
584
+ # If the request fails with a 401, make sure to strip any
585
+ # sample user/pass from the URL and try again
586
+ if (
587
+ response .status_code == 401
588
+ and (stripped_uri := strip_user_pass_url (uri ))
589
+ and stripped_uri != uri
590
+ ):
591
+ response = await self ._try_snapshot_uri (stripped_uri , auth )
582
592
583
593
if response .status_code == 401 :
584
594
raise ONVIFAuthError (f"Failed to authenticate to { uri } " )
@@ -588,6 +598,20 @@ async def get_snapshot(
588
598
589
599
return None
590
600
601
+ async def _try_snapshot_uri (
602
+ self , uri : str , auth : BasicAuth | DigestAuth | None
603
+ ) -> httpx .Response :
604
+ try :
605
+ return await self ._snapshot_client .get (uri , auth = auth )
606
+ except httpx .TimeoutException as error :
607
+ raise ONVIFTimeoutError (
608
+ f"Timed out fetching { obscure_user_pass_url (uri )} : { error } "
609
+ ) from error
610
+ except httpx .RequestError as error :
611
+ raise ONVIFError (
612
+ f"Error fetching { obscure_user_pass_url (uri )} : { error } "
613
+ ) from error
614
+
591
615
def get_definition (
592
616
self , name : str , port_type : str | None = None
593
617
) -> tuple [str , str , str ]:
0 commit comments