Параметры запроса
Параметры запроса — это гибкий способ передачи данных на ваш сервер через URL — особенно для таких вещей, как фильтры, пагинация или дополнительные входные данные. Они появляются после ?
в URL и состоят из пар ключ-значение.
Как выглядят параметры запроса?
Вот простой запрос с параметрами запроса:
GET /articles?keyword=book&page=2 HTTP/1.1
Host: example.com
В этом примере:
keyword
— это параметр запроса со значениемbook
.page
— это еще один параметр запроса со значением2
.
Эти значения передаются в URL запроса как строки обычного текста. Lihil автоматически обработает разбор и конвертацию типов на основе сигнатуры вашей функции.
Параметры запроса vs другие параметры запроса
-
Расположение в запросе Параметры запроса кодируются в URL, после параметров пути и начинаются с
?
, как часть строки запроса:GET /search?query=python&sort=asc HTTP/1.1
-
Формат кодирования Параметры запроса кодируются URL. Например:
?q=hello%20world
Это означает, что специальные символы (такие как пробелы) процентно-кодируются.
-
Типы данных Параметры запроса поддерживают:
- Примитивные типы: str, int, float, bool
- Массивы/списки: list[str], list[int]
В отличие от параметров тела, они не могут представлять вложенные структуры, такие как словари. В отличие от параметров пути, параметры запроса могут иметь повторяющиеся ключи (например, tag=python&tag=web).
Объявление параметров запроса в lihil
Вы можете объявлять параметр запроса как неявно, так и явно
Неявное объявление параметра запроса
from lihil import Route
articles = Route("/articles")
@articles.get
async def search(keyword: str, page: int = 1):
...
Если запрос поступает как /articles?keyword=book&page=2
, lihil будет:
- извлекать keyword и page из строки запроса,
- преобразовывать page в целое число (на основе аннотации типа),
- передавать оба значения в вашу функцию.
- Если page не предоставлен, будет использовано значение по умолчанию 1.
- Если параметр запроса без значения по умолчанию отсутствует или имеет недопустимый тип, который нельзя привести, lihil автоматически ответит ошибкой
InvalidRequest
.
Явное объявление параметра запроса с Param
Альтернативно, вы можете объявить параметр более явно, комбинируя typing.Annotated
и lihil.Param
.
@articles.get
async def search(keyword: Annotated[str, Param("query")], page: Annotated[int, Param("query")] = 1):
...
Параметры запроса в виде массива
В отличие от параметров пути, параметры запроса могут вести себя как двумерные данные. Это означает, что вы можете иметь несколько значений для одного и того же ключа — идеально для массивов или повторяющихся опций:
GET /filter?tag=python&tag=web&tag=backend HTTP/1.1
В lihil вы можете объявить это с типом списка:
from lihil import Route
@Route("/filter")
async def filter_by_tags(tag: list[str]):
...
lihil соберет все значения tag и даст их вам как список.
Для /filter?tag=web&tag=python&tag=backend
вы получите ["web", "python", "backend"]
как значение tag.
Валидация данных
Для параметров запроса в стиле массива lihil.Param позволяет вам устанавливать ограничения, такие как максимальная длина или валидация элементов.
from lihil import Param
Tags = Param(max_length=5)
@route("/articles")
async def search_articles(tags: Annotated[list[str], Tags]) -> JSONResponse:
...
В этом случае, если запрос включает более 5 тегов, lihil отклонит его с ошибкой 422.
Вы также можете валидировать скалярные параметры запроса таким же образом — например, для установления ограничений диапазона или правил регулярных выражений.
Page = Param(ge=1)
@route("/articles")
async def list_articles(page: Annotated[int, Page]) -> JSONResponse:
...
Пользовательская валидация
Нужен больший контроль? Вы можете определить пользовательский декодер для продвинутой логики валидации. Это работает как для одиночных, так и для основанных на списке параметров запроса.
from lihil import Param, HTTPException
class BlockedTagError(HTTPException[str]):
"This tag is not allowed"
def tag_decoder(value: str) -> str:
if value in {"banned", "spam"}:
raise BlockedTagError(f"Tag '{value}' is blocked")
return value
@route("/filter")
async def filter_tags(tags: Annotated[list[str], Param(decoder=tag_decoder)]) -> JSONResponse:
...
В этом примере, если пользователь пытается фильтровать с заблокированным тегом, таким как "banned"
или "spam"
, lihil поднимет ошибку BlockedTagError
. Запрос будет отклонен с ошибкой 422, и сообщение будет указывать, какой тег был заблокирован.
Параметры запроса — это не просто строки ключ-значение — они являются гибкой и мощной частью обработки запросов. С lihil вы получаете конвертацию типов, валидацию и структуру с минимальными усилиями.
Резюме
-
Параметры запроса появляются в URL и идеальны для фильтров, поисковых терминов и пагинации.
-
Они поддерживают как примитивные типы, так и повторяющиеся ключи (списки).
-
В lihil вы можете объявлять их неявно через аннотации типов или явно, используя Param для валидации.
-
Вы можете добавлять ограничения или пользовательские декодеры для надежной валидации ввода.