Параметры пути
В HTTP-запросе путь URL играет центральную роль в маршрутизации. Это то, как сервер знает, к какому ресурсу клиент пытается получить доступ. Но пути не просто статичны — они часто несут динамические значения, известные как параметры пути.
Как выглядят параметры пути?
Параметр пути — это переменная часть пути URL. Он обычно используется для идентификации конкретного ресурса. Например:
GET /users/42 HTTP/1.1
Host: example.com
В этом примере:
- /users/42 запрашивает пользователя, чей ID равен 42. 42 — это параметр пути — данные, встроенные непосредственно в структуру URL.
Хотя мы не можем быть полностью уверены в том, какие переменные пути в URL, RESTful API обычно следует шаблону
/entity_name_in_plural/{entity_id}/sub_entity_name_in_plurals/{sub_entity_id}/...
Здесь users
вероятно относится к сущности User
, а 42
— это значение ее ID.
Параметры пути vs другие параметры запроса
Параметры пути несут одномерные, фиксированные значения, такие как ID, slug или имена — идеальны для идентификации единого ресурса.
-
Расположение в запросе Параметры пути являются частью самого пути URL, встроенные непосредственно в структуру маршрута:
GET /users/42 HTTP/1.1
-
Формат кодирования Параметры пути кодируются URL как часть сегмента пути. Специальные символы процентно-кодируются, но они не появляются после ? — они являются частью иерархии URL.
-
Типы данных Параметры пути представляют единые, фиксированные значения и поддерживают примитивные типы, такие как:
str, int, float, bool
В отличие от параметров запроса, параметры пути не могут представлять массивы или повторяющиеся ключи. Они всегда несут точно одно значение на параметр.
-
Назначение Параметры пути обычно идентифицируют конкретный ресурс или сущность, встраивая идентификаторы в путь URL. В отличие от этого, параметры запроса используются для фильтрации, пагинации или дополнительных данных.
Объявление параметров пути в lihil
Неявное объявление параметра пути
В lihil
параметры пути являются гражданами первого класса.
вы можете объявлять параметры пути неявно, включая их в путь маршрута и сопоставляя имена аргументов функции:
Например:
from lihil import Route
user = Route("/users/{user_id}")
@user.get
async def get_user(user_id: int) -> User:
...
Здесь user_id
объявлен неявно, потому что он соответствует заполнителю {user_id}
в пути маршрута.
lihil автоматически извлекает и преобразует его из URL.
Например, Если приходит запрос вроде GET /users/42, lihil:
- извлекает 42 из URL,
- преобразует его в int (на основе аннотации типа),
- и передает его в функцию get_user.
Вам не нужно разбирать строки или получать доступ к сырому запросу вручную — lihil обрабатывает это.
Явное объявление параметра пути с lihil.Param
from lihil import Route, Param
from typing import Annotated
PositiveInt = Annotated[int, Param(gt=0)]
user = Route("/users/{user_id}")
@user.get
async def get_user(user_id: PositiveInt) -> User:
...
Валидация типов
Параметры пути валидируются на основе их аннотаций типов. Если вы объявляете параметр пути как int
, lihil автоматически преобразует его в целое число. Если конвертация не удается, lihil вернет ошибку 422 Invalid Request.
Если предоставлено объединение типов, lihil попытается преобразовать значение в каждый тип в объединении, пока один не преуспеет. Если ни один не преуспеет, возвращается ошибка 422.
Если объединение содержит str или bytes, конвертация всегда будет успешной, поскольку эти типы могут представлять любое значение. Это означает, что если у вас есть объединение вроде Union[int, str]
, параметр пути всегда будет рассматриваться как строка.
Валидация данных
Вы также можете захотеть проверить значение параметра пути. Например, если вы хотите убедиться, что ID пользователя положительный, вы можете установить такие ограничения, используя lihil.Param
.
from lihil import Route, Param
PositiveInt = Param(gt=0)
user = Route("/users/{user_id}")
@user.get
async def get_user(user_id: PositiveInt) -> User: ...
lihil.Param
позволяет вам установить различные ограничения на параметр пути, такие как минимальные и максимальные значения, регулярные выражения и многое другое. Это особенно полезно для обеспечения того, чтобы данные, которые вы получаете, были действительными перед их обработкой.
lihil.Param
использует msgspec.Meta
под капотом, поэтому вы можете использовать все функции msgspec.Meta
для валидации ваших параметров пути.
Пользовательская валидация
Вы также можете создавать пользовательские валидаторы для параметров пути. Это полезно, когда у вас есть сложная логика валидации, которую нельзя выразить простыми ограничениями.
from lihil import Route, Param, HTTPException
class MyError(HTTPException[T]):
"I don't like this value"
def decoder(value: str) -> int:
# Пользовательская логика декодирования
if value == "42":
raise MyError("I don't like this value")
return int(value)
async def create_user(user_id: int, user_age: Annotated[int, Param(decoder=decoder)]) -> User:
# Ваша логика здесь
pass
Резюме
- Параметры пути встроены непосредственно в путь URL и идентифицируют конкретные ресурсы.
- Они несут точно одно значение на параметр и поддерживают примитивные типы, такие как int, str и bool.
- В lihil вы можете объявлять параметры пути неявно в пути маршрута или явно с Param для валидации и ограничений.
- Пользовательские декодеры позволяют вам реализовать продвинутую валидацию и обработку ошибок для параметров пути.