Маршрутизація
Від #[Route] до REST-маршруту
Метод RPC-процедури потрапляє в REST, коли має атрибут Symfony\Component\Routing\Attribute\Route. Атрибут на класі необов'язковий і задає спільний шлях та назву. Методи без #[Route] лишаються лише в RPC.
| Частина | Правило |
|---|---|
| Шлях | шлях класу + / + шлях методу; порожній шлях методу дає шлях класу, обидва порожні — / |
| Назва | ufo_rest_api_ + назва класу + _ + назва методу |
| Назва класу | name з атрибута класу; без нього — псевдонім процедури з #[RPC\Info] у snake_case (shopItems → shop_items) |
| Назва методу | name з атрибута методу; без нього — назва PHP-методу в snake_case (createItem → create_item) |
| HTTP-методи | methods з атрибута методу; без них — POST |
Інші параметри #[Route] |
requirements, defaults, host тощо не використовуються: читаються лише path, name і methods |
#[RPC\Info('catalog')]
#[Route('/catalog', name: 'catalog')]
class CatalogApi implements IRpcService
{
#[Route('/items/{id}', name: 'item', methods: ['GET'])] // GET /rest/catalog/items/{id}
public function item(int $id): array {}
#[Route('/items')] // POST /rest/catalog/items
public function createItem(string $title): array {}
}
Змінні шляху ({id}) передаються в метод як параметри з тією самою назвою — див. Параметри запиту.
Шлях не виводиться з назви RPC-методу автоматично: без #[Route] метод недоступний через REST, а невідомий шлях повертає 404.
Згенеровані маршрути
Для кожного REST-методу і версії API створюються два маршрути Symfony:
| Маршрут | Шлях | HTTP-методи | Призначення |
|---|---|---|---|
<назва>_<версія> |
<шлях>, для версій, відмінних від v1, — /<версія><шлях> |
з атрибута | Виклик методу |
<назва>_<версія>_method_not_allowed |
той самий | будь-які | Пріоритет -10: неправильний HTTP-метод отримує 405, а не 404 |
Маршрути з config/router.yaml бандла:
| Маршрут | Шлях | Призначення |
|---|---|---|
ufo_rest_doc |
префікс імпорту | OpenAPI, GET |
ufo_rest_doc_ver |
/{ver} (v\d+) |
OpenAPI для версії |
ufo_rest_doc_postman |
/postman |
Postman |
ufo_rest_doc_postman_ver |
/{ver}/postman |
Postman для версії |
ufo_rest_api_entrypoint |
/{path} |
Загальний вхід, пріоритет -100: невідомий шлях повертає 404 у форматі помилок |
ufo_rest_api_entrypoint_ver |
/{ver}/{path} |
Те саме для версій, пріоритет -90 |
HEAD обробляється маршрутами GET. OPTIONS окремо не обробляється: для методу без OPTIONS у methods відповідь — 405.
Версії
Версії задає JsonRpcBundle: #[RPC\Info(version: 2, removedMethods: [...])] (Версії API). Процедура версії 2 успадковує методи версії 1, які не перевизначає і не прибирає.
| Версія | Виклик | Документація | Назва маршруту |
|---|---|---|---|
v1 (за замовчуванням) |
/rest/catalog/items/1 |
/rest, /rest/postman |
..._v1 |
v2 |
/rest/v2/catalog/items/1 |
/rest/v2, /rest/v2/postman |
..._v2 |
Невідома версія повертає 404.
Групи API та кілька входів
Імпортуйте config/router.yaml окремо для кожного входу. defaults.api_group вибирає групу API; без нього група — general. Префікс URL від назви групи не залежить.
# config/routes/ufo_rest_api.yaml
rest:
resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
prefix: /rest
trailing_slash_on_root: false
rest_internal:
resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
prefix: /internal
defaults: { api_group: internal }
trailing_slash_on_root: false
rest_partners:
resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
prefix: /partners
name_prefix: partners_
defaults: { api_group: internal }
trailing_slash_on_root: false
#[RPC\Info('catalog')]
#[RPC\APIGroups(['internal', 'public'], false)]
#[Route('/catalog', name: 'catalog')]
class CatalogApi implements IRpcService
{
#[Route('/list', name: 'list', methods: ['GET'])]
public function list(): array { return []; }
#[RPC\APIGroups(['internal'], false)]
#[Route('/price', name: 'price', methods: ['POST'])]
public function price(int $price): int { return $price; }
}
- Належність методу до груп визначає
#[RPC\APIGroups]: атрибут методу замінює атрибут класу,withDefault: trueдодаєgeneral.#[RPC\IgnoreApi]повністю виключає метод. Щоб метод з'явився в REST,#[Route]потрібен однаково. - Кожен вхід має власні методи, версії, документацію і провайдер токенів.
- Назви маршрутів отримують префікс групи:
internal_ufo_rest_doc,internal_ufo_rest_api_catalog_list_v1.name_prefixіде після нього:internal_partners_ufo_rest_doc. - Маршрути групи
generalзберігають і старі назви як псевдоніми:ufo_rest_doc→general_ufo_rest_doc. - Групу визначає лише маршрут: поле
api_groupу query чи тілі запиту її не змінює.
Поруч з RPC та іншими адаптерами
Маршрути REST реєструються через Ufo\JsonRpcBundle\Routing\IApiRouteImport (клас RestRouteImport), тож обробку груп і назв виконує завантажувач маршрутів JsonRpcBundle. RPC-, REST- і маршрути інших адаптерів, що реалізують той самий інтерфейс, можна імпортувати для тих самих груп в одному файлі без конфліктів назв.
У 1.1–1.2 для цього використовувався власний завантажувач RestYamlFileLoader; у 1.3 його видалено (див. Історію змін). Застосунків, що лише імпортують config/router.yaml, це не стосується.
Діагностика
- Методу немає в REST — перевірте
#[Route]на методі, групу API імпорту,#[RPC\IgnoreApi]іremovedMethodsверсії. 405для наявного методу — HTTP-методу немає вmethodsатрибута (за замовчуванням — лишеPOST).- Назви маршрутів —
bin/console debug:router | grep ufo_rest.