407 означает, что требуется аутентификация на прокси. 429 означает ограничение частоты запросов, но сам по себе ответ не говорит, какие запросы делят этот лимит. 502 или 504 означают проблему с ответом или таймаутом вышестоящего узла. Сначала определите, откуда пришёл ответ, затем проверяйте аутентификацию, лимиты или связность — по ситуации.
Сначала определите отвечающий уровень
HTTPS-запрос через HTTP-прокси обычно состоит из двух обменов: прокси отвечает на запрос CONNECT, затем клиент общается с целевым сервером через туннель. HTTPS-прокси добавляет TLS-соединение с прокси перед CONNECT. В обычном туннеле без перехвата TLS ответ, полученный после TLS с целевым сервером, приходит от инфраструктуры целевого сервера, которая может включать CDN или обратный прокси.
Следующий пример печатает статус CONNECT отдельно от статуса HTTP-ответа. Он требует curl 8.3 или новее и использует Basic-аутентификацию на прокси. Задайте в PROXY_URL HTTP(S)-шлюз вашего провайдера без учётных данных, а менеджер секретов пусть заполнит PROXY_USERNAME и PROXY_PASSWORD в окружении. Используйте метод аутентификации, который документирует ваш провайдер.
Сохраните это как proxy-status.sh и запустите sh proxy-status.sh без трассировки оболочки. Скрипт делает один GET-запрос, отбрасывает тело и сохраняет код выхода curl. curl импортирует учётные данные сам, поэтому оболочка не раскрывает их в аргументы команды.
: "${PROXY_URL:?Set a credential-free HTTP(S) proxy URL}"
case "$PROXY_URL" in
http://*|https://*) ;;
*) printf '%s\n' 'PROXY_URL must use http:// or https://' >&2; exit 2 ;;
esac
case "$PROXY_URL" in
*'@'*|*'?'*|*'#'*)
printf '%s\n' 'Keep credentials, queries and fragments out of PROXY_URL' >&2
exit 2 ;;
esac
curl --disable --silent --fail --http1.1 \
--noproxy '' --proxy "$PROXY_URL" --proxy-basic \
--variable %PROXY_USERNAME --variable %PROXY_PASSWORD \
--expand-proxy-user '{{PROXY_USERNAME}}:{{PROXY_PASSWORD}}' \
--connect-timeout 5 --max-time 15 --retry 0 \
--output /dev/null \
--write-out 'exit=%{exitcode} http=%{http_code} connect=%{http_connect} seconds=%{time_total}\n' \
'https://example.com/'--disable стоит первым, чтобы игнорировать настройки curlrc, а --noproxy '' не даёт унаследованному исключению обойти выбранный шлюз. Пятисекундный бюджет на соединение и пятнадцатисекундный общий бюджет — отправные точки для этой небольшой диагностики. Команда не следует редиректам и не делает повторов, а печатает числовые результаты без подробной трассировки. Эти опции описаны в руководстве curl.
Руководство по прокси в curl описывает простую форму -x, переменные http_proxy и https_proxy и SOCKS5 через socks5h — они определяют, куда уходит запрос, ещё до появления любого из этих кодов статуса.
Читайте поля вместе. connect=407 означает, что прокси запросил аутентификацию во время CONNECT. connect=200 http=429 означает, что туннель был принят, а HTTP 429 пришёл уже после. http=000 означает, что для передачи не был записан статус HTTP-ответа; смотрите статус CONNECT и код выхода curl. Успешный CONNECT не гарантирует, что установление TLS или передача тела завершились.
Для целевого сервера по простому HTTP туннеля обычно нет. Прокси пересылает запрос, поэтому возвращённый статус может прийти как от прокси, так и от целевого сервера. Заголовки провайдера и брендированные страницы ошибок могут дать подсказки, но внешний вид сам по себе не устанавливает отправителя. Когда атрибуция остаётся неясной, используйте документированные ошибки провайдера или диагностику запросов.
407 Proxy Authentication Required
407 обязан содержать вызов Proxy-Authenticate. Клиент может повторить запрос с Proxy-Authorization; заголовок Authorization для целевого сервера аутентификацию на прокси не обеспечивает. Эти требования взяты из RFC 9110, раздел 15.5.8.
Начните с этих проверок:
- Убедитесь, что шлюз, имя пользователя и пароль соответствуют действующей конфигурации провайдера.
- Проверьте, что учётные данные находятся в настройке аутентификации на прокси, а не в настройке аутентификации на целевом сервере.
- Если провайдер кодирует таргетинг по стране или сессии в имени пользователя, сверьтесь с его документированным форматом. Как сообщается о некорректном таргете, зависит от провайдера.
- Если библиотека требует URL прокси с учётными данными, кодируйте имя пользователя и пароль по отдельности, чтобы зарезервированные символы не могли изменить структуру URL.
Руководство по исправлению 407 описывает диагностику аутентификации. Руководство по Python Requests демонстрирует явную настройку прокси и кодирование учётных данных. Следуйте документированному формату библиотеки, прежде чем добавлять повторы.
429 Too Many Requests
429 сообщает об ограничении частоты запросов. RFC 6585, раздел 4 намеренно оставляет идентификацию пользователя и подсчёт запросов на усмотрение отвечающего сервиса. Лимит может относиться к аккаунту, учётным данным, сессии, адресу, ресурсу или сервису в целом.
Отправитель подсказывает, чью политику изучать. Прокси может применять лимит тарифа или конкурентности; целевой сервер может применять собственный лимит запросов. Ни в одном из случаев область действия по одному статусу не определяется. Читайте детали ответа и документированный лимит и соблюдайте Retry-After, когда он передан.
Снижайте трафик в затронутой области. Для общего лимита аккаунта это может означать координацию всех воркеров, использующих этот аккаунт. Для лимита, привязанного к одному ресурсу, — замедление запросов к этому ресурсу. Если область неизвестна, снижайте конкурентность на время разбирательства. Смена исходящего адреса не означает, что лимит сбросился.
Backoff тоже нуждается в границе: если требуемое ожидание превышает оставшийся дедлайн задачи, остановитесь или запланируйте работу на потом. Многократные повторы в одном и том же окне лимита добавляют нагрузку, не снимая лимит.
502 и 504: сбой или задержка вышестоящего узла
502 Bad Gateway означает недопустимый ответ вышестоящего узла. 504 Gateway Timeout означает, что шлюз не получил своевременный ответ от вышестоящего узла. Их определения в HTTP не указывают отказавший компонент.
В пуле прокси проверяйте исходящий узел, промежуточные шлюзы и целевой сервер. Используйте диагностику провайдера и небольшой авторизованный контрольный запрос, чтобы сузить область сбоя. Сравнивая шлюзы, держите настройки целевого сервера и клиента одинаковыми и меняйте по одной переменной за раз.
Важны три решения на стороне клиента:
- Безопасен ли повтор. Для одобренного запроса, который безопасно повторять, допустите небольшое число попыток с backoff в рамках общего дедлайна. Неудачный ответ на запись не доказывает, что запись не была применена. Проверьте состояние операции или документированный механизм идемпотентности, прежде чем отправлять её заново. См. семантику повторов в HTTP.
- Сколько задача может ждать. Задавайте дедлайны исходя из бюджета задержки задачи. Более короткий дедлайн клиента ограничивает ожидание, но не устраняет сбой вышестоящего узла. Руководство по таймаутам объясняет бюджеты соединения, передачи и всей задачи.
- Какие сбои растут. Отслеживайте 502 и 504 отдельно по шлюзу, целевому серверу и региону вместе с долей успеха на уровне приложения. Изменение, ограниченное одним маршрутом, — повод изучить этот маршрут, а не доказательство нездоровья всего пула.
Используйте новое соединение или другой исходящий узел только тогда, когда такая смена соответствует диагнозу и требованиям сессии. Новый исходящий узел может также изменить контекст сессии пользователя, поэтому это не универсальная стратегия повтора.
403 и ответы HTTP 200 с непригодным содержимым
403 означает отказ. Он может отражать политику доступа forward-прокси или отказ инфраструктуры целевого сервера. Проверьте отвечающий уровень и его документированную причину, прежде чем менять учётные данные, заголовки или адреса.
Сложнее обнаружить ответ HTTP 200, содержащий страницу проверки, экран входа или неполную оболочку приложения. Статус фиксирует исход HTTP; ваше приложение должно дополнительно проверять нужное ему содержимое. Например, задача по данным о товарах должна проверять ожидаемый идентификатор товара и обязательные поля, а не просто слово, которое может встретиться и на странице ошибки.
Приведённая выше диагностическая команда отбрасывает тело. Руководство по Python точно так же демонстрирует настройку и проверку статуса, поэтому боевому клиенту нужна собственная проверка тела, специфичная для целевого сервера. Наблюдения по Amazon и Google показывают, почему эта дополнительная проверка важна.
Выберите следующую проверку
Используйте эту таблицу после определения отвечающего уровня. Это стартовые проверки, а не доказательство первопричины.
| Наблюдаемый результат | Что изучать | Первое действие |
|---|---|---|
| CONNECT 407 | Аутентификация на прокси | Проверьте вызов, конфигурацию учётных данных и аккаунт провайдера. |
| CONNECT 429 или 429 от целевого сервера | Лимит отвечающего сервиса | Соблюдайте Retry-After и снижайте трафик в документированной области. |
| 502 или 504 | Сбой ответа или тайминга вышестоящего узла | Сравните диагностику; повторяйте только работу, безопасную для повтора, в рамках её бюджета. |
| CONNECT 403 или 403 от целевого сервера | Политика доступа или авторизация | Проверьте, какой уровень отклонил запрос и почему. |
| HTTP 200 с неполным или неожиданным телом | Критерии успеха приложения | Проверяйте обязательное содержимое, прежде чем засчитывать успех. |
| Нет HTTP-статуса | Прогресс соединения, туннеля или TLS | Прочитайте код выхода curl и следуйте проверкам стадий из руководства по таймаутам. |
Для повторяющихся измерений методика бенчмарка объясняет транспортные логи, распределения времени и их пределы. Держите результат по содержимому и любую диагностику провайдера рядом с этими логами, чтобы подсчёт статусов не превратился в необоснованное объяснение.