Помилки проксі в httpx і aiohttp

Асинхронні бібліотеки Python налаштовують проксі інакше, ніж requests, і по-своєму повідомляють про відмови. Нижче зібрано тексти помилок, які вони видають, і що кожен означає.

Оновлено · Редакція Prokso

Коротко
  • У httpx з версії 0.28.0 параметра proxies немає: проксі задається через proxy= або mounts=
  • Відмову проксі httpx видає як ProxyError, aiohttp як ClientHttpProxyError, а слово після 407 називає причину
  • SOCKS у httpx потребує httpx[socks], а в aiohttp працює лише через пакет aiohttp-socks

Що означає помилка

У httpx проксі задається параметром proxy=. Старий параметр proxies= оголосили застарілим у версії 0.26.0 і прибрали у 0.28.0, тому тепер він дає TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. Якщо проксі не прийняв запит CONNECT, httpx видає httpx.ProxyError з кодом і текстом відповіді, наприклад 407 NO_USER. Якщо до проксі не вдалося під'єднатися, це вже httpx.ConnectError.

В aiohttp помилка під'єднання до проксі — ClientProxyConnectionError з текстом Cannot connect to host gw.prokso.com:823. Відмова на CONNECT — ClientHttpProxyError, наприклад 407, message='NO_USER'. Зверніть увагу: у тексті цього винятку є адреса проксі разом із логіном і паролем, тож не публікуйте такі журнали.

SOCKS обидві бібліотеки підтримують лише через додаткові пакети. Httpx без них пише Using SOCKS proxy, but the 'socksio' package is not installed і радить pip install httpx[socks]. В aiohttp вбудованої підтримки SOCKS немає зовсім: потрібен пакет aiohttp-socks.

Причини

  • Старий параметр proxies у httpx. Код, написаний для версій до 0.28, падає з TypeError одразу при створенні клієнта.
  • Логін, пароль або ліміт. 407 NO_USER означає хибні дані входу, TRAFFIC_EXHAUSTED і THREADS_EXHAUSTED вказують на ліміти плану. Для сайтів на https:// це виняток, для http:// звичайна відповідь зі статусом 407.
  • SOCKS без додаткового пакета. Httpx не має socksio, а aiohttp отримав рядок socks5:// у параметрі proxy=. Aiohttp такий рядок не відхиляє, а надсилає на порт SOCKS звичайний HTTP-запит CONNECT, і помилка виходить незрозумілою.
  • Хибний хост чи порт. ConnectError у httpx і ClientProxyConnectionError в aiohttp: у рядку не gw.prokso.com або порт поза 823, 824 і 10000–20000.
  • Схема https:// у рядку проксі. Порт 823 чекає звичайний HTTP. Документація httpx радить писати http:// навіть для https-сайтів, а aiohttp має лише обмежену підтримку проксі з https://.

Як виправити

  1. У httpx замініть proxies= на httpx.Client(proxy='http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823'). Для різних проксі під різні адреси використовуйте mounts=.
  2. Для SOCKS у httpx встановіть pip install 'httpx[socks]' і пишіть proxy='socks5h://ЛОГІН:ПАРОЛЬ@gw.prokso.com:824'. Схему socks5h httpx приймає з версії 0.28.0.
  3. В aiohttp передавайте логін і пароль у самому рядку: session.get(url, proxy='http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823'). Параметр proxy_auth з версії 3.14 оголошено застарілим.
  4. Для SOCKS в aiohttp встановіть aiohttp-socks і створіть сесію з ProxyConnector.from_url('socks5://ЛОГІН:ПАРОЛЬ@gw.prokso.com:824'). Цей метод приймає схеми socks5, socks4 і http, а назву сайту для SOCKS5 за замовчуванням перетворює на IP проксі (параметр rdns). Повний приклад є в інструкції aiohttp.
  5. Обробляйте 407 за текстом відповіді: NO_USER означає перевірити логін і список IP, TRAFFIC_EXHAUSTED поповнити трафік, THREADS_EXHAUSTED зменшити кількість одночасних задач до 1000 на план. Усі порти й формати рядка зібрано в довіднику про шлюз.

Як перевірити, що все запрацювало

Зробіть запит до https://prokso.com/ip тим самим клієнтом і з тим самим рядком проксі. Якщо у відповіді JSON з IP, країною та ASN проксі, налаштування правильне. Рядок також можна перевірити без коду в перевірці проксі, щоб відділити помилку в коді від помилки в даних.

Діагностика за 2 хвилини

Спершу вставте рядок у перевірку проксі. Якщо там проксі працює, причина в програмі чи її налаштуваннях. Якщо ні — перевірте рядок з терміналу:

curl -v -x "http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823" https://api.ipify.org
  • Рядок < HTTP/1.1 407 одразу після CONNECT — відповідає проксі. Назва після коду, наприклад NO_USER, підказує причину.
  • Проксі відповів на CONNECT кодом 200, а далі прийшов інший код — проксі працює, цю відповідь дав сайт.
  • Жодної відповіді, лише тайм-аут — з'єднання не дійшло до проксі: перевірте хост, порт і мережу.

Інструкції, де трапляється ця помилка

Питання й відповіді

Чому httpx пише ProxyError: 407, а для http-сайту повертає відповідь?

Для https:// клієнт відкриває тунель CONNECT, і відмова в ньому стає винятком. Для http:// запит іде до проксі напряму, і 407 приходить як звичайна відповідь. Що означає код, пояснено на сторінці <a href="/errors/407-proxy-authentication-required">407 Proxy Authentication Required</a>.

Чи бере aiohttp проксі зі змінних середовища?

За замовчуванням ні. Змінні HTTP_PROXY і HTTPS_PROXY читаються лише тоді, коли сесію створено з trust_env=True.

Чи можна писати socks5h в aiohttp-socks?

У пакеті python-socks, на якому працює aiohttp-socks, метод from_url приймає socks5, а не socks5h. Перетворення назви сайту на IP на боці проксі для SOCKS5 там увімкнене за замовчуванням. Про сам протокол — у глосарії: <a href="/glossary/socks5">SOCKS5</a>.

Резидентські $1.59, мобільні $2.50, серверні $0.65 за 1 ГБ

Реєстрація за хвилину, доступи одразу після оплати.

Створити акаунт