Перейти к содержанию

Файлы cookie

В этом разделе рассматривается, как извлекать и проверять cookie с помощью Rapidy.

Вы можете проверить данные, используя любой тип, поддерживаемый pydantic.

Описание

Cookie — это небольшой набор данных о пользователе, который хранится на его устройстве без изменений и какой-либо обработки.

Веб-клиент при каждом обращении к соответствующему сайту передаёт эти данные веб-серверу в составе HTTP-запроса.

Cookie позволяет получить конкретный cookie по его имени.

from rapidy.http import get, Cookie

@get('/')
async def handler(
    user_id: str = Cookie(alias='UserID'),
) -> ...:
from rapidy.http import get, Cookie

@get('/')
async def handler(
    user_id: str = Cookie(alias='UserID'),
    user_session: str = Cookie(alias='UserSession'),
) -> ...:

Извлечение всех cookies

Cookies позволяет извлечь сразу все cookies.

Извлечение в заранее заданную схему

pydantic.BaseModel

from pydantic import BaseModel, Field
from rapidy.http import get, Cookies

class CookieData(BaseModel):
    user_id: str = Field(alias='UserID')
    user_session: str = Field(alias='User-Session')

@get('/')
async def handler(
    cookie_data: CookieData = Cookies(),
) -> ...:

dataclasses.dataclass

dataclasses.dataclass поддерживаются в качестве модели, но задать alias стандартными средствами dataclasses невозможно.

from dataclasses import dataclass
from rapidy.http import get, Cookies

@dataclass
class CookieData:
    UserID: str  # camelCase syntax if cookie name is 'UserID'
    user_session: str  # cannot extract if cookie name is 'User-Session'

@get('/')
async def handler(
    cookie_data: CookieData = Cookies(),
) -> ...:
# {"errors": [{"type": "missing", "loc": ["cookie", "user_session"], "msg": "Field required"}]}

Извлечение в словарь

from rapidy.http import get, Cookies

@get('/')
async def handler(
    cookie_data: dict[str, str] = Cookies(),
) -> ...:
# {'UserID': ..., 'User-Session': ...}

Извлечение без валидации

Отключение валидации не рекомендуется.

Если отключить валидацию, параметр вернёт базовую структуру aiohttp:

  • Cookiestr
  • CookiesMapping[str, str]

Способы отключения валидации

Явное отключение

from rapidy.http import get, Cookie, Cookies

@get('/')
async def handler_1(
    user_id: int = Cookie(alias='UserID', validate=False)
) -> ...:
    # ...

@get('/')
async def handler_2(
    cookie_data: int = Cookies(validate=False)
) -> ...:
    # # {'UserID': ..., 'User-Session': ...}

Использование Any

from typing import Any

@get('/')
async def handler_1(
    user_id: Any = Cookie(alias='UserID', validate=False)
) -> ...:
    # ...

@get('/')
async def handler_2(
    cookie_data: Any = Cookies(validate=False)
) -> ...:
    # # {'UserID': ..., 'User-Session': ...}

Отсутствие аннотации типа

Если тип не указан, по умолчанию будет установлен Any.

@get('/')
async def handler_1(
    user_id=Cookie(alias='UserID')
) -> ...:
    # ...

@get('/')
async def handler_2(
    cookie_data=Cookies()
) -> ...:
    # # {'UserID': ..., 'User-Session': ...}

Значения по умолчанию

Значение по умолчанию для Cookie будет использоваться, если в поступившем запросе не будет найден cookie с таким именем.

Значение по умолчанию для Cookies будет использоваться, если в поступившем запросе не будет найдено ни одного cookie.

Использование default

@get('/')
async def handler(
    some_cookie: str = Cookie(alias='Some-Cookie', default='SomeValue'),
) -> ...:
from typing import Annotated

@get('/')
async def handler(
    some_cookie: Annotated[str, Cookie(alias='Some-Cookie', default='SomeValue')],
) -> ...:
from typing import Annotated

@get('/')
async def handler(
    some_cookie: Annotated[str, Cookie(alias='Some-Cookie')] = 'SomeValue',
) -> ...:

Использование default_factory

@get('/')
async def handler(
    some_cookie: str = Cookie(alias='Some-Cookie', default_factory=lambda: 'SomeValue'),
) -> ...:
from typing import Annotated

@get('/')
async def handler(
    some_cookie: Annotated[str, Cookie(alias='Some-Cookie', default_factory=lambda:'SomeValue')],
) -> ...:

Нельзя одновременно использовать default и default_factory.

При попытке указать оба параметра будет вызвано исключение pydantic:

TypeError('cannot specify both default and default_factory')

Предупреждения и особенности

Невозможно использовать Cookie и Cookies одновременно в одном обработчике.

@get('/')
async def handler(
    user_id: str = Cookie(alias='UserID'),
    cookie_data: CookieData = Cookies(),
) -> ...:

При запуске приложения будет вызвано исключение AnotherDataExtractionTypeAlreadyExistsError.

------------------------------
Attribute with this data extraction type cannot be added to the handler - another data extraction type is already use in handler.

Handler path: `main.py`
Handler name: `handler`
Attribute name: `cookie_data`
------------------------------

Атрибут alias в Cookies

Атрибут alias не работает в параметре Cookies().

@get('/')
async def handler(
    cookie_data: CookieData = Cookies(alias='SomeName'),  # <-- alias not working
) -> ...:

Как извлекаются сырые данные

Внутри Rapidy используется метод cookies объекта Request, после чего полученные данные передаются в pydantic для валидации.

Как происходит извлечение внутри Rapidy

async def extract_cookies(request: Request) -> Mapping[str, str]:
    return request.cookies

Rapidy использует встроенные механизмы aiohttp

Подробнее об объекте aiohttp.Request и методах извлечения данных можно узнать здесь.