Parse and validate a proxy. Args: proxy: proxy. Returns: Parsed proxy. Raises: InvalidProxy: If ``proxy`` isn't a valid proxy.
(proxy: str)
| 46 | |
| 47 | |
| 48 | def parse_proxy(proxy: str) -> Proxy: |
| 49 | """ |
| 50 | Parse and validate a proxy. |
| 51 | |
| 52 | Args: |
| 53 | proxy: proxy. |
| 54 | |
| 55 | Returns: |
| 56 | Parsed proxy. |
| 57 | |
| 58 | Raises: |
| 59 | InvalidProxy: If ``proxy`` isn't a valid proxy. |
| 60 | |
| 61 | """ |
| 62 | parsed = urllib.parse.urlparse(proxy) |
| 63 | if parsed.scheme not in ["socks5h", "socks5", "socks4a", "socks4", "https", "http"]: |
| 64 | raise InvalidProxy(proxy, f"scheme {parsed.scheme} isn't supported") |
| 65 | if parsed.hostname is None: |
| 66 | raise InvalidProxy(proxy, "hostname isn't provided") |
| 67 | if parsed.path not in ["", "/"]: |
| 68 | raise InvalidProxy(proxy, "path is meaningless") |
| 69 | if parsed.query != "": |
| 70 | raise InvalidProxy(proxy, "query is meaningless") |
| 71 | if parsed.fragment != "": |
| 72 | raise InvalidProxy(proxy, "fragment is meaningless") |
| 73 | |
| 74 | scheme = parsed.scheme |
| 75 | host = parsed.hostname |
| 76 | port = parsed.port or (443 if parsed.scheme == "https" else 80) |
| 77 | username = parsed.username |
| 78 | password = parsed.password |
| 79 | # urllib.parse.urlparse accepts URLs with a username but without a |
| 80 | # password. This doesn't make sense for HTTP Basic Auth credentials. |
| 81 | if username is not None and password is None: |
| 82 | raise InvalidProxy(proxy, "username provided without password") |
| 83 | |
| 84 | try: |
| 85 | proxy.encode("ascii") |
| 86 | except UnicodeEncodeError: |
| 87 | # Input contains non-ASCII characters. |
| 88 | # It must be an IRI. Convert it to a URI. |
| 89 | host = host.encode("idna").decode() |
| 90 | if username is not None: |
| 91 | assert password is not None |
| 92 | username = urllib.parse.quote(username, safe=DELIMS) |
| 93 | password = urllib.parse.quote(password, safe=DELIMS) |
| 94 | |
| 95 | return Proxy(scheme, host, port, username, password) |
| 96 | |
| 97 | |
| 98 | def get_proxy(uri: WebSocketURI) -> str | None: |
searching dependent graphs…