Перейти к основному содержимому

Запрос

Прежде чем углубляться в структуру и детали HTTP-запроса, важно понять, что такое запрос на самом деле.

В контексте веб-разработки HTTP-запрос — это сообщение, которое клиент отправляет серверу, запрашивая выполнение какого-либо действия — такого как получение веб-страницы или отправка данных. Это начальная точка почти каждого взаимодействия между клиентом и вашим сервером.

Хотя lihil абстрагирует большинство низкоуровневых деталей — позволяя вам напрямую объявлять заголовки, параметры запроса, cookies и содержимое тела как структурированные входные данные для вашей конечной точки — все еще полезно понимать, как выглядит запрос под капотом.

Запрос в виде обычного текста

На самом низком уровне HTTP-запрос — это просто обычный текст, отправляемый по сети, следующий протоколу HTTP. Вот пример простого GET-запроса:

GET /path?query=value HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml

Это показывает базовую структуру:

  • Метод (GET) сообщает серверу, какое действие запрашивается.

  • Путь "/path" указывает на ресурс "path"

  • "?query=value" включает параметр запроса "query" со значением "value".

  • Версия HTTP указана в конце первой строки.

Дополнительные строки — это заголовки, такие как Host, User-Agent и Accept, которые предоставляют метаданные о запросе.

Запросы также могут нести тело. Например, POST-запрос может выглядеть так:

POST /submit HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 27

{"key":"value"}

Здесь запрос включает тело, которое содержит JSON-данные. Заголовки, такие как Content-Type и Content-Length, описывают, как сервер должен интерпретировать тело.

Объявление объекта запроса в вашей конечной точке

lihil предоставляет абстракции более высокого уровня, такие как Header, Query, Body и т.д., чтобы позволить вам напрямую объявлять параметры, которые вам нужны в вашей конечной точке. В большинстве случаев вы не взаимодействуете с IRequest напрямую, но понимание того, откуда поступает эта информация, поможет вам понять, как фреймворк работает под капотом.

from lihil import Route
from lihil.interface import IRequest

@Route("create_uesrs")
async def ep(req: IRequest):
data = await req.body()

Разбор параметров в lihil оптимизирован. Обычно это не принесет значительного прироста производительности при использовании объекта IRequest напрямую.

Интерфейс IRequest

class IRequest(Protocol):
def __init__(self, scope: IScope, receive: IReceive | None = None) -> None: ...
def __getitem__(self, key: str) -> Any: ...
def __iter__(self) -> Iterator[str]: ...
def __len__(self) -> int: ...
def __eq__(self, value: object) -> bool: ...
def __hash__(self) -> int: ...
@property
def url(self) -> URL: ...
@property
def headers(self) -> Mapping[str, str]: ...
@property
def query_params(self) -> Mapping[str, str]: ...
@property
def path_params(self) -> Mapping[str, Any]: ...
@property
def cookies(self) -> Mapping[str, str]: ...
@property
def client(self) -> IAddress | None: ...
@property
def state(self) -> dict[str, Any]: ...
@property
def method(self): ...
@property
def receive(self) -> IReceive: ...
async def stream(self) -> AsyncGenerator[bytes, None]: ...
async def body(self) -> bytes: ...
async def json(self) -> Any: ...
def form(
self,
*,
max_files: int | float = 1000,
max_fields: int | float = 1000,
max_part_size: int = 1024 * 1024,
) -> AsyncContextManager[FormData]: ...
async def close(self) -> None: ...
async def is_disconnected(self) -> bool: ...
async def send_push_promise(self, path: str) -> None: ...