1- """Device connectivity checking utilities.
1+ """Target connectivity checking utilities.
22
3- This module provides functions to check device reachability and authentication
3+ This module provides functions to check target reachability and authentication
44requirements before launching the browser capture.
55"""
66
1010import ssl
1111import urllib .error
1212import urllib .request
13+ from urllib .parse import urlparse
1314
1415_LOGGER = logging .getLogger (__name__ )
1516
1617
17- def check_device_connectivity ( ip : str , timeout : int = 5 ) -> tuple [bool , str , str | None ]:
18- """Check if device is reachable and determine the correct URL scheme.
18+ def _parse_target ( target : str ) -> tuple [str , str | None ]:
19+ """Parse a target string into hostname and optional scheme.
1920
20- Tries HTTP first, then HTTPS if HTTP fails.
21+ Handles various input formats:
22+ - Full URL: "https://example.com" -> ("example.com", "https")
23+ - URL with path: "https://example.com/page" -> ("example.com", "https")
24+ - Hostname only: "example.com" -> ("example.com", None)
25+ - IP address: "192.168.1.1" -> ("192.168.1.1", None)
26+ - IP with port: "192.168.1.1:8080" -> ("192.168.1.1:8080", None)
2127
2228 Args:
23- ip: Device IP address
29+ target: URL, hostname, or IP address
30+
31+ Returns:
32+ Tuple of (hostname_with_port, scheme_or_none)
33+ """
34+ # Check if it looks like a URL (has scheme)
35+ if "://" in target :
36+ parsed = urlparse (target )
37+ host = parsed .netloc or parsed .path .split ("/" )[0 ]
38+ return host , parsed .scheme
39+ # No scheme - return as-is
40+ return target , None
41+
42+
43+ def check_device_connectivity (target : str , timeout : int = 5 ) -> tuple [bool , str , str | None ]:
44+ """Check if target is reachable and determine the correct URL scheme.
45+
46+ Tries the provided scheme first (if any), otherwise tries HTTP then HTTPS.
47+
48+ Args:
49+ target: URL, hostname, or IP address (e.g., "example.com", "https://example.com", "192.168.1.1")
2450 timeout: Connection timeout in seconds
2551
2652 Returns:
2753 Tuple of (reachable, scheme, error_message)
28- - reachable: True if device responded
54+ - reachable: True if target responded
2955 - scheme: "http" or "https"
3056 - error_message: None if reachable, otherwise describes the problem
3157 """
32- for scheme in ["http" , "https" ]:
33- url = f"{ scheme } ://{ ip } /"
58+ # Parse target to extract hostname and any provided scheme
59+ host , provided_scheme = _parse_target (target )
60+
61+ # Determine which schemes to try
62+ if provided_scheme in ("http" , "https" ):
63+ schemes_to_try = [provided_scheme ]
64+ else :
65+ schemes_to_try = ["http" , "https" ]
66+
67+ last_error : str | None = None
68+
69+ for scheme in schemes_to_try :
70+ url = f"{ scheme } ://{ host } /"
3471 try :
3572 req = urllib .request .Request (url , method = "GET" )
3673 if scheme == "https" :
@@ -43,17 +80,15 @@ def check_device_connectivity(ip: str, timeout: int = 5) -> tuple[bool, str, str
4380 urllib .request .urlopen (req , timeout = timeout )
4481 return True , scheme , None
4582 except urllib .error .HTTPError :
46- # HTTP error means device is reachable (might need auth, that's fine)
83+ # HTTP error means target is reachable (might need auth, that's fine)
4784 return True , scheme , None
4885 except urllib .error .URLError as e :
4986 # Connection refused, timeout, etc - try next scheme
50- if scheme == "https" :
51- return False , "http" , f"Cannot connect to device at { ip } : { e .reason } "
87+ last_error = str (e .reason )
5288 except Exception as e :
53- if scheme == "https" :
54- return False , "http" , f"Cannot connect to device at { ip } : { e } "
89+ last_error = str (e )
5590
56- return False , "http" , f"Cannot connect to device at { ip } "
91+ return False , schemes_to_try [ 0 ] , f"Cannot connect to { host } : { last_error } "
5792
5893
5994def check_basic_auth (url : str , timeout : int = 5 ) -> tuple [bool , str | None ]:
0 commit comments