Для заголовка, который определяет оператор прокси, Requests предоставляет HTTPAdapter.proxy_headers как точку переопределения:

from urllib.parse import urlsplit
import requests
from requests.adapters import HTTPAdapter

class TaggedProxy(HTTPAdapter):
    def proxy_headers(self, proxy):
        headers = super().proxy_headers(proxy)
        endpoint = urlsplit(proxy)
        if (endpoint.scheme == 'http'
                and endpoint.hostname == 'proxy.example'
                and endpoint.port == 8080):
            headers['X-Proxy-Account'] = 'department-a'
        return headers

with requests.Session() as session:
    adapter = TaggedProxy()
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    response = session.get(
        'https://service.example/data',
        proxies={'https': 'http://proxy.example:8080'},
        timeout=15,
    )

X-Proxy-Account — пример поля, которое понимает именно этот прокси, а не стандартный способ аутентификации у любого посредника.

Начните с super().proxy_headers(proxy). Requests использует этот метод для создания Proxy-Authorization, когда URL содержит учётную запись Basic. Замена всего результата может лишить этого поведения.

Адаптер передаёт эти значения в ProxyManager из urllib3. В туннеле HTTPS они сопровождают CONNECT. Обычное сопоставление заголовков запроса описывает последующий запрос к месту назначения.

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

При обычной пересылке HTTP полям прокси по-прежнему нужна предполагаемая политика потребления посредника. То, что заголовок специфичен для прокси в клиентском API, не гарантирует конфиденциальность, если прокси передаёт его дальше.

Похожие статьи