Source code for ogu_api.proxy

from __future__ import annotations

import re

__all__ = ['Proxy']

_AUTH_AT_PATTERN = re.compile(r'^([^:@]+):([^:@]+)@([^:]+):(\d+)$')


[docs] class Proxy: """Normalize proxy strings to the ``http://...`` form ``tls_client`` expects. Accepts: - ``user:pass@host:port`` (standard URL form) - ``host:port:user:pass`` (proxy-list form) - ``host:port`` (no auth) Existing scheme prefixes (``http://``, ``socks5://``, etc.) are stripped before matching; the result is always ``http://...``. Args: proxy: Raw proxy string in any of the accepted forms. ``None`` to disable. Attributes: proxy: Normalized proxy URL, or ``None`` when no input was provided or the input couldn't be parsed. Example: >>> Proxy('user:pass@host:8080').proxy 'http://user:pass@host:8080' >>> Proxy('host:8080:user:pass').proxy 'http://user:pass@host:8080' >>> Proxy('host:8080').proxy 'http://host:8080' """ def __init__(self, proxy: str | None = None) -> None: self.proxy: str | None = self._format_proxy(proxy) @staticmethod def _format_proxy(proxy: str | None) -> str | None: if not proxy: return None proxy = re.sub(r'^[a-z]+://', '', proxy.strip()) auth_at_match = _AUTH_AT_PATTERN.match(proxy) if auth_at_match: username, password, hostname, port = auth_at_match.groups() return f'http://{username}:{password}@{hostname}:{port}' parts = proxy.split(':') if len(parts) == 4: if parts[1].isdigit(): hostname, port, username, password = parts return f'http://{username}:{password}@{hostname}:{port}' username, password, hostname, port = parts if port.isdigit(): return f'http://{username}:{password}@{hostname}:{port}' if len(parts) == 2 and parts[1].isdigit(): hostname, port = parts return f'http://{hostname}:{port}' return None