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