--- title: Разложить сессию по запросу description: Отметьте на модели сессии, какие поля уходят в query и заголовки, и получите вход и обновление без ручной сборки. sources: - eazy_sdk.auth.Placed - eazy_sdk.auth.session_scheme - eazy_sdk.auth.Bearer api_fingerprint: "sha256:dd79449c2df640d41104d3dc64ba72ec9b7bf1cd73acfa16c7def44b6522f82a" --- Не каждая сессия помещается в один заголовок `Authorization`. Веб-почта передаёт токен страницы и адрес ящика в query каждого вызова, а ключ устройства отправляет заголовком. Все три значения принадлежат одной сессии и появляются после одного входа. Отметьте поля модели сессии маркером `Placed`. Схема, вход на первом защищённом вызове и обновление после `401` строятся из этой модели. ```{literalinclude} ../../../../../../examples/docs/auth_placed.py :language: python :start-after: "# region docs: auth-placed-model" :end-before: "# endregion docs: auth-placed-model" ``` `session_scheme(MailSession)` читает маркеры и возвращает схему. Роутер получает её через `security`, а корень SDK связывает схему с учётными данными и сервисом входа одной строкой: `MAIL_SESSION.configure(credentials=..., service=...)`. Вместо `credentials=` можно передать готовую `session=`, тогда вход не выполняется. | Маркер | Куда уходит значение | Тип поля | |---|---|---| | `Placed.query("token")` | параметр query | строка или `SecretStr` | | `Placed.header("X-Device", prefix="")` | заголовок | строка или `SecretStr` | | `Placed.body("token")` | поле тела запроса | строка или `SecretStr` | `secret=False` снимает скрытие значения в диагностике. Оставьте его только для несекретных полей, таких как адрес ящика. `Bearer()` остаётся коротким написанием для `Placed.header("Authorization", prefix="Bearer ")`. Оба маркера живут на одной модели, если сервису нужны и токен в заголовке, и что-то ещё. Куки маркером не размещают. Куки, которые поставил сайт, библиотека несёт сама, когда корень объявил `Cookies(...)`; об этом рассказывает руководство {doc}`о сессии на куках `. :::{dropdown} Запускаемый файл целиком ```{literalinclude} ../../../../../../examples/docs/auth_placed.py :language: python ``` ::: ```text folders: Inbox, Sent request: token=page-token-42&email=ada%40mail.example | X-Device: device-42 ``` ## Сессия рядом с параметрами запроса Некоторые сайты передают сессию там же, где остальные параметры вызова: в query у чтения и в форме у записи. Запишите оба места на одном поле через `|`: `Placed.body("token") | Placed.query("token")`. Места читаются слева направо, и для каждой операции берётся первое, которое у неё есть. Query и заголовки есть у любого запроса. Тело есть у операции, которая объявила плоские поля тела: `Form[...]` или `JsonField[...]`. В такой операции значение сессии становится ещё одним полем тела в её собственной кодировке, а в query не попадает. Операция без тела получает значение в query. Поля сессии встают в конец тела, после полей операции и значений `Inject`. Если сервер чувствителен к порядку, задайте его целиком через `Wire(order=FieldOrder(body=(...)))`. Тело целиком из модели и тело из `BodyProjection` местом для сессии не считаются. Составное тело (`Part`) не поддерживается: такая операция отклоняется до отправки запроса. ## Когда сессия считается пригодной Сессия с пустым размещаемым значением в запрос не уходит. Пустая строка или `None` в отмеченном поле означают, что отправлять нечего, и SDK выполняет вход заново. Поля без маркера на пригодность не влияют. Срок действия по-прежнему задаёт `ExpiresAt`. ## Что проверяется при объявлении `session_scheme(...)` отклоняет модель сразу, без запроса: | Объявление | Причина отказа | |---|---| | два поля с `Placed.query("token")` | одно место запроса принимает одно поле | | `Placed.query(...)` на словаре или списке | одно место принимает одно значение | | два поля с `Bearer()` | заголовок авторизации один | | только `Placed.body(...)`, а у операции нет плоских полей тела | значение некуда положить; отказ приходит на первом вызове операции | Модель без единого маркера допустима только на сайте, который ведёт сессию на куках. В остальных случаях первый защищённый вызов заканчивается ошибкой настройки: такая сессия ничего не кладёт в запрос. ## Дальше - {doc}`Соберите вход на сайте с куками `. - {doc}`Передайте сохранённую сессию и пропустите вход `. - {doc}`Обновите сессию после отказа `.