# Справочник HTTP-клиента

Основные классы импортируются из `duckonet`. Там, где нужен импорт из отдельного модуля, указан полный путь. Все значения по умолчанию и ограничения относятся к версии 0.11.5.

<a id="constructor"></a>
## HttpClient и AsyncHttpClient

Все аргументы конструктора передаются по имени. Используйте `with HttpClient(...)` для синхронного кода и `async with AsyncHttpClient(...)` для асинхронного. Подготовка установки и проверка профиля выполняются при входе в контекст.

| Аргумент | Значение по умолчанию и назначение |
|---|---|
| api_key | Обязательная строка с API-ключом DuckoLab. Не используется для авторизации на целевом сайте. |
| browser | Семейство профиля: `'chrome'` (по умолчанию) или `'edge'`. Доступные версии определяются каталогом и правами API-ключа. |
| version | `None` — выбрать доступную версию при открытии; полная строка — закрепить её; `"last"` — подготавливать обновления и выбирать их между полными прогонами `client.run()`. |
| application | `h2` — вариант сетевого профиля по умолчанию. Для обычного выбора HTTP-протокола удобнее параметр `protocol`. Подробнее о вариантах — в разделе [Client и AsyncClient](legacy.html). |
| protocol | По умолчанию не задан: используется `application`. Принимает `h1`, `h2`, `h3`, `auto` и имеет приоритет над `application`. `h1` выбирает HTTP/1.1; `h3` и `auto` допускают HTTP/2 с последующим переходом на HTTP/3. Обычный proxy URL не поддерживает `h3`/`auto`. Явный `MasqueProxy` с `protocol='h3'` выбирает строгий H3 через HTTPS/H2 CONNECT-UDP; AUTO для MASQUE не предоставляется. Фактический протокол — `response.protocol`. |
| state_dir | None — каталог ~/.duckonet/default. Можно передать собственный постоянный путь. |
| check_interval | `300` секунд; целое число от 0 до 3600. Минимальный интервал между проверками обновлений при открытии клиента. При 0 проверка выполняется при каждом открытии нового клиента. |
| allow_offline | True — разрешить работу с ещё действительными локальными файлами при недоступности сервиса. Подписи, сроки и права продолжают проверяться. |
| channel, bundle | None — штатный подписанный канал и комплект файлов. Задаются для собственной схемы поставки. |
| profile_id | None, явный ID подписанного профиля. |
| ca_bundle | `None` — стандартная настройка доверенных CA. Можно указать путь к PEM-файлу сертификатов для HTTPS-соединения; это не переключатель отключения проверки. |
| proxy | None — прямое подключение; иначе URL-строка или ProxyRoute. |
| cookie_policy | None — стандартная политика; иначе CookiePolicyOptions для хранилища cookies. |
| headers | None — без собственных общих заголовков; иначе словарь, пары или Headers. |
| cookies | None — без добавочных cookies. Заданные значения применяются к каждому запросу, но не заполняют хранилище. |
| timeout_seconds | `30` секунд. Общее время подготовки и выполнения одного запроса, включая перенаправления. Число больше 0 и не больше 300. Интервал запуска клиента сюда не входит. |
| allow_redirects, max_redirects | True и 20; строго bool и целое 0..100. |
| body_limit, header_limit | `1048576` и `65536` байт. Лимит тела ответа в памяти и лимит сохраняемых заголовков. Целые числа от 1 до `67108864` (64 MiB) и от 1 до `1048576` (1 MiB) соответственно. |
| cookies_enabled, persist_cookies | `True`/`True`. Первое управляет отправкой cookies, второе — сохранением `Set-Cookie` из ответов в памяти клиента. На диск эти параметры cookies не сохраняют. |
| encoding | None — UTF-8 при отправке. Для ответа явно указанная кодировка имеет приоритет над charset и UTF-8. |
| preserve_url, diagnostics, allow_downgrade | False, строго bool: сохранение формы пути URL, включение диагностики и разрешение переходов HTTPS → HTTP соответственно. |

`client.cookies` возвращает хранилище cookies открытой сессии, `client.capabilities` — её возможности. `distribution` даёт доступ к управлению установкой. До входа в контекст `startup_info` равно `None`; после входа содержит результат подготовки. Объект открывается только один раз; после закрытия создавайте новый экземпляр. Запрос к закрытому или ещё не открытому клиенту отклоняется с кодом `STARTUP_CLIENT_NOT_OPEN`.

<a id="methods"></a>
## Методы

`request(method, url, **kwargs)` возвращает `HttpResponse`. Сокращённые методы `get`, `head`, `post`, `put`, `patch`, `delete` и `options` принимают `url` и те же именованные аргументы. У асинхронного клиента они вызываются с `await`.

Через `request()` допустимы стандартные методы, включая `TRACE`, и дополнительные методы с корректным HTTP-именем. `CONNECT` запрещён. Стандартные имена приводятся к верхнему регистру; регистр дополнительных имён сохраняется.

`stream(method, url, **kwargs)` открывает поток через `with` или `async with`. `consume(method, url, consumer, *, chunk_size=65536, **kwargs)` передаёт части тела обработчику `consumer` и возвращает `HttpResponse`. Размер части — целое число от 1 до 16777216 байт. Асинхронный обработчик может вернуть объект, поддерживающий `await`. Если обработчик вызвал исключение, оно передаётся после закрытия контекста. `close()` и `await close()` завершают работу клиента.

Клиент сохраняет до восьми сочетаний варианта профиля и прокси, включая исходный маршрут. Повторное использование сочетания не расходует новый слот. Попытка создать девятый маршрут вызывает `ValueError`; для другого набора маршрутов создайте отдельный клиент. Все маршруты одного клиента используют общее хранилище cookies.

<a id="request-options"></a>
## Аргументы запроса

Для `request()` обязательны `method` и `url`. URL должен быть абсолютным адресом HTTP(S). Логин и пароль в адресе, пробелы, управляющие символы и обратная косая черта запрещены. Фрагмент после `#` удаляется. Порт проверяется до чтения переданных файлов. Ограничения IDNA и IPv6 приведены [ниже](reference.html).

| Аргумент | Назначение |
|---|---|
| params=None | Словарь или упорядоченные пары; `params=None` не добавляет параметры. Повторы сохраняются, значения list/tuple разворачиваются. `None` внутри отдельного поля означает пустое значение: `params={"q": None}` даёт `q=`. Параметры дополняют существующую строку запроса. |
| headers | Если не задано — заголовки клиента. Явные пары заменяют все его поля с теми же именами без учёта регистра; остальные сохраняются. Новые поля добавляются в переданном порядке. None очищает собственные заголовки клиента для этого запроса, пустой список — не очищает. |
| body | bytes; отсутствие отличается от b''. |
| data | bytes, str либо словарь/пары для формы URL-encoded. None означает явно присутствующее пустое тело. |
| json | Значение для сериализации: словарь, список, строка, число, `bool` или `None`. `json=None` отправляет JSON `null`. Используется UTF-8; Unicode сохраняется, NaN запрещён. |
| files=None | Словарь или пары. Значение: bytes, бинарный читаемый объект, (filename, content) или (filename, content, content_type). Тип по умолчанию — application/octet-stream. Вместе с files можно передать поля формы через data. |
| encoding | Если не задано — настройка клиента. None выбирает UTF-8 для отправки и charset либо UTF-8 для ответа. JSON требует UTF-8. |
| cookies | Если не задано — добавочные cookies клиента. None или пустые пары убирают эту добавку для запроса; автоматическое хранилище продолжает работать. |
| cookies_enabled, persist_cookies | Если не задано — настройка клиента; строго bool. |
| proxy, protocol | Если не заданы — маршрут клиента. proxy=None явно выбирает прямое соединение. protocol: h1, h2, h3 или auto. |
| timeout_seconds | Если не задано — таймаут клиента. Число больше 0 и не больше 300 секунд. |
| allow_redirects, max_redirects, allow_downgrade | Настройки клиента, bool/int 0..100/bool. |
| body_limit, header_limit | Если не заданы — настройки клиента. Размеры в байтах; диапазоны те же, что в конструкторе. |
| preserve_url, diagnostics | Настройки клиента, если не заданы; иначе bool. preserve_url не сохраняет фрагмент и не отключает проверку URL. |
| context | `BrowserHopContext` с исходной страницей, сайтом верхнего уровня и правилами cookies. Нужен, когда контекст отличается от URL самого запроса. Допустимы `mode="cors"`, `preflight=False`; `body_present` должен соответствовать наличию тела. Сам контекст не запускает CORS-проверки или preflight. |
| advanced=None | Словарь только с timeout_ms, body_limit, header_limit и context. Нельзя одновременно задать тот же параметр напрямую. advanced.timeout_ms конфликтует с timeout_seconds. Неизвестные имена отклоняются. |

Приоритет настроек: аргумент запроса → настройка клиента → значение по умолчанию. `advanced.timeout_ms` принимает целое число от 1 до 300000 миллисекунд. `timeout_seconds` задаётся в секундах и округляется вверх до миллисекунд, минимум — 1 мс.

Общий таймаут начинается при подготовке HTTP-вызова. Он включает кодирование тела, чтение файлов, выбор маршрута, перенаправления, заголовки, тело ответа и обработчик `consume()`. Он не включает регистрацию и обновление при входе в клиент. Блокирующий Python-вызов `file.read()` или обработчик нельзя прервать посередине: срок проверяется после возврата управления. Отдельных таймаутов подключения и чтения в этом API пока нет.

`body` нельзя сочетать с `data`, `json` или `files`; `json` — с `data` или `files`. Для JSON и формы `Content-Type` добавляется, если вы не задали его явно. Для multipart разделитель и `Content-Type` выбирает библиотека; собственный `Content-Type` вместе с `files` запрещён. Максимальный размер отправляемого тела — 16777216 байт (16 MiB), включая разделители multipart.

У обычного ответа лимит тела по умолчанию — 1 MiB, максимум — 64 MiB. Например, `body_limit=10*1024*1024` разрешает сохранить 10 MiB. При потоковом чтении этот параметр ограничивает внутренний буфер, а не общий объём скачивания.

Ответ gzip уже распакован в `content`; лимит применяется к распакованным данным. Повторно вызывать `gzip.decompress()` не нужно. Заголовки `Content-Encoding` и `Content-Length` могут описывать исходный сжатый ответ. 

Имена заголовков должны быть допустимыми ASCII-именами HTTP; значения принимаются как `str` или `bytes` в Latin-1. Управляющие символы запрещены, кроме HTAB. Библиотека сама управляет `Host`, `Content-Length`, `Transfer-Encoding`, `Connection`, `Proxy-Connection`, `Upgrade`, `Trailer`, `TE` и псевдозаголовками HTTP/2 и HTTP/3.

Для авторизации прокси задавайте учётные данные маршрута, а не `Proxy-Authorization`. Заголовок `Cookie` проходит те же правила, что параметр `cookies`. Профильные `User-Agent`, `Accept`, `Accept-Language` и `Accept-Encoding` применяются к HTTP и HTTPS; защищённые Client Hints — только к HTTPS. Допустимое явно заданное значение заменяет профильное поле с тем же именем. Ответ при этом сохраняет `assurance=custom-request`.

<a id="redirects"></a>
## Перенаправления

При `allow_redirects=True` клиент следует перенаправлениям 301, 302, 303, 307 и 308. При `False` он возвращает исходный ответ 3xx. `history` содержит предыдущие ответы `HttpResponse`; `response.url` — конечный URL в `bytes`. Ответ 3xx без `Location` возвращается без перехода.

`HttpRedirectError` содержит `code` и ответ текущего перехода в `response`. Возможные коды: `HTTP_REDIRECT_LOCATION_AMBIGUOUS` — несколько `Location`; `HTTP_REDIRECT_LOCATION_INVALID` — пустой или неверный адрес; `HTTP_REDIRECT_LIMIT` — превышен лимит; `HTTP_REDIRECT_DOWNGRADE` — запрещён переход HTTPS → HTTP.

301 и 302 меняют POST на GET. 303 меняет на GET любой метод, кроме GET и HEAD. При такой замене удаляются тело и заголовки `content-type`, `content-encoding`, `content-language`, `content-location`. 307 и 308 сохраняют метод и тело.

При смене origin (схемы, хоста или порта) удаляются `Authorization`, `Cookie`, `Cookie2`, `Proxy-Authorization` и одноразовые cookies запроса. Хранилище выбирает подходящие cookies для нового URL. При сохранении origin одноразовые cookies продолжают действовать. Повторный переход на тот же URL допустим: ответ мог изменить cookies. Циклы ограничивает `max_redirects`; список предыдущих URL в контексте выбора cookies ограничен 100 записями.

<a id="response"></a>
## HttpResponse

`HttpResponse(raw_response, history=(), encoding=None)` — неизменяемая обёртка над исходным `Response`. `history` хранится как кортеж, `encoding` задаёт кодировку ответа. Следующие поля доступны непосредственно у ответа:

| Поле | Тип и назначение |
|---|---|
| status_code | int — HTTP-код |
| protocol | int — фактический протокол: 1, 2 или 3 |
| body, content | bytes или None — сохранённое тело. `None` означает, что в этом объекте тела нет, например при потоковом чтении. |
| url | bytes — конечный URL |
| blocks | tuple[ResponseBlock] — сохранённые блоки ответа |
| request_id, owner_id, epoch | int — идентификаторы запроса и владельца |
| outcome | int — результат выполнения на нативном уровне |
| body_complete | bool — получено ли тело полностью |
| body_bytes_received | int — число полученных байт |
| tls_verified | bool — признак завершённой проверки TLS. У потокового ответа итоговое значение читайте после `result()`. |

`content` возвращает `raw_response.body`. `raw_headers` — кортеж пар `(bytes, bytes)` финального блока, `headers` — объект `Headers`, сохраняющий повторы. `reason` всегда равно `None`: нативный ответ не содержит текстовую фразу статуса. `assurance` всегда равно `custom-request`. Поля `diagnostics` и `timings` содержат словарь либо `None`, если наблюдение недоступно.

`text` вызывает `decode()`. Метод `decode(encoding=None, errors='strict')` выбирает кодировку в порядке: аргумент метода → `response.encoding` → charset из `Content-Type` → UTF-8. При `content=None` методы `decode()`, `json()` и свойство `text` вызывают `ValueError`.

`json(*, encoding=None, **kwargs)` декодирует текст и вызывает `json.loads()` с переданными аргументами. Ошибки Unicode и JSON передаются вызывающему коду. `raise_for_status()` вызывает `HTTPStatusError` только для кодов 400–599; исключение содержит `response` и `status_code`.

<a id="headers"></a>
## Headers и подготовка запроса

`Headers(values=())` принимает словарь, последовательность пар или другой `Headers`. Сохраняет регистр, порядок и повторяющиеся имена. `[name]` и `get(name, default)` ищут без учёта регистра и возвращают первое значение. `get_all(name)` возвращает кортеж всех значений, `multi_items()` — все пары в исходном порядке.

Итерация возвращает уникальные имена в первом написании; `len()` считает уникальные имена. Повторные `Set-Cookie` не склеиваются. `repr()` показывает количество полей, не их значения.

Если нужно подготовить запрос без отправки, используйте вспомогательные средства из `duckonet.http_models306`:

- `UNSET` — отсутствие аргумента, отличное от явного `None`.
- `MAX_REQUEST_BODY=16777216` — предел тела запроса.
- `normalize_headers(headers=None)` — проверяет исходящие заголовки и возвращает `Headers`.
- `encode_request(method, url, *, params=None, headers=None, body=UNSET, data=UNSET, json=UNSET, files=None, encoding=None)` — подготавливает метод, URL, заголовки и тело без отправки. Переданные файлы читает во время вызова и оставляет открытыми.

Результат кодирования — неизменяемый `EncodedRequest`: `method` и `url` имеют тип `str`, `headers` — кортеж пар строк, `body` — `bytes`, `body_present` и `custom_headers` — `bool`, `assurance` — `str`. Значение `profile-defaults` означает отсутствие собственных заголовков, `custom-request` — их наличие. Это описание настроек, а не проверка совпадения сетевого отпечатка. У итогового `HttpResponse` значение остаётся `custom-request`.

Имена полей URL и формы принимаются как `str` или `bytes`. Значения — `str`, `bytes`, `int`, `float`, `bool`, `None` либо список или кортеж этих типов. Файловый объект должен возвращать байты. Открытие и закрытие переданного файла остаётся обязанностью приложения.



<a id="url-support"></a>
## Поддержка URL

Передавайте полный URL строкой, например `https://example.com/api/items`. Фрагмент после `#` не отправляется. Параметры `params` дополняют существующую строку запроса; библиотека не меняет `http://` на `https://`.

Unicode-домен не преобразуется автоматически в IDNA. IPv6-адрес непосредственно в URL, например `https://[::1]/`, у этого интерфейса не поддерживается: запрос завершается ошибкой возможности до подключения. Не путайте это ограничение с обработкой адреса прокси — у него отдельные правила.

`HttpResponse.url` возвращает конечный адрес в виде `bytes`. Если нужна строка, декодируйте его явно. Параметр `preserve_url=True` сохраняет форму пути, но не отменяет проверку адреса и удаление фрагмента.


## WebSocket

`client.websocket(url, **options)` возвращает sync/async менеджер контекста. После открытия доступны `send`, `recv`, `ping`, `close`, `abort`, свойства handshake/selected_subprotocol/generation_receipt. Параметры, сроки, очереди, cookies, ошибки и примеры описаны полностью в [руководстве WebSocket](websocket.html).

## Полные прогоны и длительные соединения

[run(), browser_profile и profile_update_status](profile-updates.html) описаны вместе с правилами смены профиля. [websocket()](websocket.html) открывает WebSocket; [MasqueProxy](masque.html) задаёт маршрут HTTP/3 через совместимый прокси. Эти возможности доступны синхронному и асинхронному HTTP-клиенту.
