"""Safe HTTP client: open URLs only for allowed schemes (e.g. https, http) to avoid path traversal (CWE-22)."""

from urllib.request import Request, urlopen
from urllib.parse import urlparse


def safe_urlopen(
    request: Request,
    timeout: float = 10,
    allowed_schemes: tuple[str, ...] = ("https", "http"),
) -> "urlopen":
    """Open URL only if its scheme is in allowed_schemes; otherwise raise ValueError.

    Use this instead of raw urlopen() to satisfy Bandit B310 and prevent opening
    file:// or other non-HTTP schemes.

    Args:
        request: urllib.request.Request (has .full_url or .get_full_url()).
        timeout: Timeout in seconds for the request.
        allowed_schemes: Tuple of lowercase scheme names, e.g. ("https", "http").

    Returns:
        Context manager from urlopen (use with 'with').

    Raises:
        ValueError: If the request URL scheme is not in allowed_schemes.
    """
    url = request.get_full_url()
    parsed = urlparse(url)
    scheme = (parsed.scheme or "").lower()
    if scheme not in allowed_schemes:
        raise ValueError(
            f"URL scheme not allowed: {scheme!r} (allowed: {allowed_schemes})"
        )
    # Scheme validated above; only https/http reach here (B310).
    return urlopen(request, timeout=timeout)  # nosec B310
