# HTTP_PROXY и NO_PROXY: проверка без сети

Переменная с адресом прокси есть, но программа ведёт себя иначе, чем ожидается. До проверки пароля и покупки другого тарифа полезно ответить на более узкий вопрос: какие параметры видит именно этот клиент?

Ниже воспроизводимый опыт с двумя функциями стандартной библиотеки Python. Он проверяет выбор переменных и исключений без запроса к сайту. Все адреса учебные; настоящие логины, пароли и настройки вашей машины в вывод не попадают.

Материал подготовлен Portproof, сервисом прокси, eSIM и SMS. Это самостоятельная техническая заметка нашей публикации. Мы не измеряем здесь скорость соединения и не проверяем доступность какого-либо сайта. При подготовке использовался ИИ; границы проверки и источники указаны в тексте.

## Сначала отделите три решения

Для обращения к HTTPS-сайту приложению нужно выбрать настройки для схемы назначения, определить, попадает ли узел в исключения, и только затем выполнить соединение. Наличие `HTTP_PROXY` ещё не доказывает, что HTTPS-запрос использует этот адрес. Значение `http://…` у HTTPS-прокси может быть правильным: это схема подключения к шлюзу, а не схема целевого сайта.

Есть и другой уровень: переменные вашего терминала не обязательно совпадают с окружением IDE, контейнера, службы или фонового задания. Проверка в соседнем окне терминала исследует другой процесс. Не выводите всё окружение рабочего процесса в общий журнал: среди переменных могут быть секреты.

Наш опыт использует `getproxies_environment()` и `proxy_bypass_environment()` из `urllib.request`. Это вспомогательные функции конкретной реализации CPython. Публичный `getproxies()` может дополнительно читать системные настройки, когда переменные не дали конфигурацию. Мы эту ветку не запускаем. Результат нельзя автоматически переносить на Requests, Node.js, браузер или Docker.

## Что проверить в выборе переменных

В синтетическом окружении задаём только нужные значения. Контекст `patch.dict(..., clear=True)` временно скрывает исходное окружение внутри отдельного тестового процесса и восстанавливает его после проверки. Код ничего не записывает в профиль оболочки или настройки системы.

| Входные данные | Результат проверяемой функции |
|---|---|
| Только `HTTP_PROXY` | Адрес читается для схемы HTTP |
| Разные `HTTP_PROXY` и `http_proxy` | Выбирается значение в нижнем регистре |
| `HTTP_PROXY` вместе с `REQUEST_METHOD` | Значение HTTP в верхнем регистре игнорируется |
| `http_proxy` вместе с `REQUEST_METHOD` | Значение в нижнем регистре сохраняется |
| Непустая `HTTP_PROXY` и пустая `http_proxy` | Пустое нижнее значение убирает настройку |

Особенность `REQUEST_METHOD` связана с CGI и обработкой входных заголовков. Не удаляйте защитный признак из рабочего окружения ради прохождения теста. Если приложение должно использовать явную конфигурацию, настройте её предусмотренным клиентом способом.

## Исключение — отдельное решение

Следующий небольшой фрагмент можно запустить без сети. Он показывает именно результат функции, которая проверяет список исключений:

```python
from urllib.request import proxy_bypass_environment

cases = [
    ("api.example", "example", True),
    ("notexample", "example", False),
    ("api.example:8443", "example:8443", True),
    ("api.example:443", "example:8443", False),
    ("api.example", "*", True),
    ("192.0.2.7", "192.0.2.0/24", False),
]
for host, no_proxy, expected in cases:
    actual = proxy_bypass_environment(host, {"no": no_proxy})
    assert actual is expected, (host, no_proxy)
    print(host, no_proxy, actual)
```

`True` здесь означает попадание в исключение для прямого маршрута. Это не подтверждение успешного соединения напрямую. Поддомен `api.example` совпадает с суффиксом `example`, а похожая строка `notexample` — нет. Если в правиле указан порт, не считайте его правилом для любого порта.

Проверка с CIDR намеренно показывает границу опыта: данная функция не разворачивает подсеть `192.0.2.0/24` в набор адресов. Другой клиент может трактовать такой список иначе. Поэтому копирование одного `NO_PROXY` во все инструменты требует отдельной проверки каждого клиента.

31 октября 2026 года полный локальный набор из 13 сценариев прошёл на CPython 3.12.14. Обращения к сокетам были запрещены тестом; их число осталось нулевым. Проверена логика выбора синтетических настроек. DNS, операционная система, авторизация, туннель CONNECT и реальный маршрут запроса этим опытом не проверены.

## Как применить результат к своей задаче

Запишите имя клиента и его версию, способ запуска, схему целевого URL и источник настроек. Для исключений сохраните только учебный аналог имени узла; пароль для такого расследования не нужен. Затем выберите один источник настройки и повторите небольшой разрешённый запрос в самом приложении.

Если нужен пример с явным обработчиком и авторизацией, используйте [инструкцию по прокси в Python urllib](https://portproof.org/ru/guides/python-urllib-proxy). Когда curl работает, а приложение нет, [порядок сравнения двух клиентов](https://portproof.org/ru/guides/proxy-works-in-curl-but-not-in-your-app) помогает отделить окружение от сетевой ошибки. Общие поля разобраны в [настройках прокси](https://portproof.org/ru/guides/what-are-proxy-settings).

Источник для поведения публичных интерфейсов: [документация Python 3.12](https://docs.python.org/3.12/library/urllib.request.html#urllib.request.getproxies). Версию используемой библиотеки проверяйте отдельно: этот опыт — зафиксированная проверка, а не обещание одинакового поведения всех HTTP-клиентов.

