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 skrócie
  • 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ć

  1. W httpx zamień proxies= na httpx.Client(proxy='http://LOGIN:HASŁO@gw.prokso.com:823'). Dla różnych proxy pod różne adresy używaj mounts=.
  2. Dla SOCKS w httpx zainstaluj pip install 'httpx[socks]' i pisz proxy='socks5h://LOGIN:HASŁO@gw.prokso.com:824'. Schemat socks5h httpx przyjmuje od wersji 0.28.0.
  3. 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.
  4. 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.
  5. 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 407 zaraz po CONNECT oznacza, że odpowiada proxy. Nazwa po kodzie, na przykład NO_USER, wskazuje przyczynę.
  • Proxy odpowiedziało na CONNECT kodem 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>.

Rezydencjalne $1.59, mobilne $2.50, serwerowe $0.65 za 1 GB

Rejestracja w minutę, dostęp od razu po płatności.

Utwórz konto