Multipart Form Data
Чтение тела запроса как multipart/form-data
.
Описание
Form Data (MIME-type: multipart/form-data
) — один из наиболее часто используемых типов содержимого для передачи двоичных данных на сервер.
Формат multipart означает, что данные отправляются на сервер отдельными частями. Каждая часть может иметь свой тип содержимого, имя файла и сами данные. Разделение данных происходит с помощью граничной строки.
from pydantic import BaseModel, ConfigDict
from rapidy.http import post, Body, ContentType, FileField
class UserData(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
username: str
password: str
image: FileField
@post('/')
async def handler(
user_data: UserData = Body(content_type=ContentType.m_part_form_data),
# or
user_data: UserData = Body(content_type='multipart/form-data'),
) -> ...:
Пример данных
POST / HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=---WD9146A
Content-Length: ...
---WD9146A
Content-Disposition: form-data; name="username"
User
---WD9146A
Content-Disposition: form-data; name="password"
myAwesomePass
---WD9146A
Content-Disposition: form-data; name="image"; filename="image.png";
Content-Type: image/png
<... binary data ...>
---WD9146A
Отправка с помощью curl
Извлечение без валидации
Отключение валидации не рекомендуется.
Если валидация отключена, параметр будет содержать базовую структуру aiohttp
:
Body(content_type=ContentType.m_part_form_data) → MultiDictProxy[Union[str, bytes, FileField]]
Способы отключения валидации
Явное отключение
from pydantic import BaseModel
from rapidy.http import post, Body, ContentType
class BodyData(BaseModel):
...
@post('/')
async def handler(
data: BodyData = Body(validate=False, content_type=ContentType.m_part_form_data),
) -> ...:
Использование Any
@post('/')
async def handler(
data: Any = Body(content_type=ContentType.m_part_form_data),
) -> ...:
Отсутствие аннотации типа
Если не указывать тип, по умолчанию будет установлен Any
.
Значения по умолчанию
Если HTTP-запрос не содержит тела, параметр получит указанное значение по умолчанию (если оно задано).
Примеры использования
Указано значение по умолчанию
from pydantic import BaseModel
from rapidy.http import post, Body, ContentType
class BodyData(BaseModel):
...
@post('/')
async def handler(
data: BodyData = Body('some_data', content_type=ContentType.m_part_form_data),
# or
data: BodyData = Body(default_factory=lambda: 'some_data', content_type=ContentType.m_part_form_data),
) -> ...:
Опциональное тело запроса
from pydantic import BaseModel
from rapidy.http import post, Body, ContentType
class BodyData(BaseModel):
...
@post('/')
async def handler(
data: BodyData | None = Body(content_type=ContentType.m_part_form_data),
# or
data: Optional[BodyData] = Body(content_type=ContentType.m_part_form_data),
# or
data: Union[BodyData, None] = Body(content_type=ContentType.m_part_form_data),
) -> ...:
Извлечение сырых данных
Rapidy
использует метод post
объекта Request
для получения данных и передает их в Pydantic
для валидации.
Как происходит извлечение внутри Rapidy
Rapidy
использует встроенные механизмы aiohttp
Подробнее об объекте aiohttp.Request
и методах извлечения данных можно узнать
здесь.
x-www-form-urlencoded
и multipart/form-data
обрабатываются одинаково.
Оба этих типа данных извлекаются через метод post
объекта Request
. Это особенность реализации aiohttp
.
Однако если параметр аннотирован как bytes
или StreamReader
, данные извлекаются иначе.
Подробнее об объекте StreamReader
можно узнать здесь.
bytes
from rapidy.http import post, Body, ContentType
@post('/')
async def handler(
user_data: bytes = Body(content_type=ContentType.m_part_form_data),
# also you can use pydantic validation
user_data: bytes = Body(content_type=ContentType.m_part_form_data, min_length=1),
) -> ...:
Внутренний код Rapidy
StreamReader
from rapidy import StreamReader
from rapidy.http import post, Body, ContentType
@post('/')
async def handler(
user_data: StreamReader = Body(content_type=ContentType.m_part_form_data),
) -> ...:
Внутренний код Rapidy
Валидация Pydantic
для StreamReader
не поддерживается.
Значение по умолчанию для StreamReader
задать нельзя.
Если попытаться установить значение по умолчанию для Body
с аннотацией StreamReader
через default
или default_factory
,
будет вызвана ошибка ParameterCannotUseDefaultError
.