Błędy proxy w httpx i aiohttp
Asynchroniczne biblioteki Pythona konfigurują proxy inaczej niż requests i po swojemu zgłaszają odmowy. Poniżej zebrano treści błędów, które zwracają, i co każdy z nich oznacza.
Zaktualizowano · Redakcja Prokso
- W httpx od wersji 0.28.0 nie ma parametru proxies: proxy ustawia się przez proxy= lub mounts=
- Odmowę proxy httpx zgłasza jako ProxyError, aiohttp jako ClientHttpProxyError, a słowo po 407 nazywa przyczynę
- SOCKS w httpx wymaga httpx[socks], a w aiohttp działa tylko przez pakiet aiohttp-socks
Co oznacza błąd
W httpx proxy ustawia się parametrem proxy=. Stary parametr proxies= uznano za przestarzały w wersji 0.26.0 i usunięto w 0.28.0, więc teraz daje TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. Jeśli proxy nie przyjęło żądania CONNECT, httpx zgłasza httpx.ProxyError z kodem i tekstem odpowiedzi, na przykład 407 NO_USER. Jeśli z proxy w ogóle nie udało się połączyć, jest to już httpx.ConnectError.
W aiohttp błąd połączenia z proxy to ClientProxyConnectionError z tekstem Cannot connect to host gw.prokso.com:823. Odmowa na CONNECT to ClientHttpProxyError, na przykład 407, message='NO_USER'. Uwaga: w treści tego wyjątku jest adres proxy razem z loginem i hasłem, więc nie publikuj takich logów.
SOCKS obie biblioteki obsługują tylko przez dodatkowe pakiety. Httpx bez nich pisze Using SOCKS proxy, but the 'socksio' package is not installed i radzi pip install httpx[socks]. W aiohttp wbudowanej obsługi SOCKS nie ma wcale: potrzebny jest pakiet aiohttp-socks.
Przyczyny
- Stary parametr proxies w httpx. Kod napisany dla wersji sprzed 0.28 wywraca się z TypeError od razu przy tworzeniu klienta.
- Login, hasło lub limit. 407 NO_USER oznacza błędne dane logowania, a TRAFFIC_EXHAUSTED i THREADS_EXHAUSTED wskazują limity planu. Dla stron na https:// to wyjątek, dla http:// zwykła odpowiedź ze statusem 407.
- SOCKS bez dodatkowego pakietu. Httpx nie ma socksio albo aiohttp dostał linię socks5:// w parametrze proxy=. Aiohttp nie odrzuca takiej linii, tylko wysyła na port SOCKS zwykłe żądanie HTTP CONNECT, a błąd wychodzi niezrozumiały.
- Błędny host lub port. ConnectError w httpx i ClientProxyConnectionError w aiohttp: w linii nie ma gw.prokso.com lub port jest spoza 823, 824 i 10000–20000.
- Schemat https:// w linii proxy. Port 823 czeka na zwykły HTTP. Dokumentacja httpx radzi pisać http:// nawet dla stron https, a aiohttp ma tylko ograniczoną obsługę proxy z https://.
Jak to naprawić
- W httpx zamień
proxies=nahttpx.Client(proxy='http://LOGIN:HASŁO@gw.prokso.com:823'). Dla różnych proxy pod różne adresy używajmounts=. - Dla SOCKS w httpx zainstaluj
pip install 'httpx[socks]'i piszproxy='socks5h://LOGIN:HASŁO@gw.prokso.com:824'. Schemat socks5h httpx przyjmuje od wersji 0.28.0. - W aiohttp przekazuj login i hasło w samej linii:
session.get(url, proxy='http://LOGIN:HASŁO@gw.prokso.com:823'). Parametr proxy_auth od wersji 3.14 jest przestarzały. - Dla SOCKS w aiohttp zainstaluj aiohttp-socks i utwórz sesję z
ProxyConnector.from_url('socks5://LOGIN:HASŁO@gw.prokso.com:824'). Ta metoda przyjmuje schematy socks5, socks4 i http, a nazwę strony dla SOCKS5 domyślnie zamienia na IP po stronie proxy (parametr rdns). Pełny przykład jest w instrukcji aiohttp. - Obsługuj 407 według tekstu odpowiedzi: NO_USER oznacza sprawdzenie loginu i listy IP, TRAFFIC_EXHAUSTED doładowanie transferu, THREADS_EXHAUSTED zmniejszenie liczby jednoczesnych zadań do 1000 na plan. Wszystkie porty i formaty linii zebrano w opisie bramy.
Jak sprawdzić, czy działa
Wyślij żądanie do https://prokso.com/ip tym samym klientem i z tą samą linią proxy. Jeśli w odpowiedzi jest JSON z IP, krajem i ASN proxy, konfiguracja jest poprawna. Linię możesz też sprawdzić bez kodu w sprawdzarce proxy, aby oddzielić błąd w kodzie od błędu w danych.
Diagnoza w 2 minuty
Najpierw wklej linię do sprawdzania proxy. Jeśli tam proxy działa, przyczyna leży w programie lub jego ustawieniach. Jeśli nie - sprawdź linię z terminala:
curl -v -x "http://LOGIN:HASŁO@gw.prokso.com:823" https://api.ipify.org
- Wiersz
< HTTP/1.1 407zaraz poCONNECToznacza, że odpowiada proxy. Nazwa po kodzie, na przykładNO_USER, wskazuje przyczynę. - Proxy odpowiedziało na
CONNECTkodem 200, a potem przyszedł inny kod - proxy działa, tę odpowiedź dała strona. - Brak odpowiedzi, tylko przekroczony czas - połączenie nie dotarło do proxy: sprawdź host, port i sieć.
Instrukcje, w których pojawia się ten błąd
Pytania i odpowiedzi (FAQ)
Dlaczego httpx zgłasza ProxyError: 407, a dla strony http zwraca odpowiedź?
Dla https:// klient otwiera tunel CONNECT i odmowa w nim staje się wyjątkiem. Dla http:// żądanie idzie do proxy bezpośrednio, a 407 przychodzi jako zwykła odpowiedź. Co oznacza kod, wyjaśnia strona <a href="/pl/errors/407-proxy-authentication-required">407 Proxy Authentication Required</a>.
Czy aiohttp bierze proxy ze zmiennych środowiskowych?
Domyślnie nie. Zmienne HTTP_PROXY i HTTPS_PROXY są odczytywane tylko wtedy, gdy sesję utworzono z trust_env=True.
Czy w aiohttp-socks można pisać socks5h?
W pakiecie python-socks, na którym działa aiohttp-socks, metoda from_url przyjmuje socks5, a nie socks5h. Zamiana nazwy strony na IP po stronie proxy jest tam dla SOCKS5 włączona domyślnie. O samym protokole w słowniczku: <a href="/pl/glossary/socks5">SOCKS5</a>.
Inne błędy proxy
Rezydencjalne $1.59, mobilne $2.50, serwerowe $0.65 za 1 GB
Rejestracja w minutę, dostęp od razu po płatności.