Маршрутизація

← Маршрутизація

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

uk/docs/api/rest-bundle/routing.md новий файл +126 −0

1 + # Маршрутизація
2 +
3 + ## Від `#[Route]` до REST-маршруту
4 +
5 + Метод RPC-процедури потрапляє в REST, коли має атрибут `Symfony\Component\Routing\Attribute\Route`. Атрибут на класі необов'язковий і задає спільний шлях та назву. Методи без `#[Route]` лишаються лише в RPC.
6 +
7 + | Частина | Правило |
8 + | --- | --- |
9 + | Шлях | шлях класу + `/` + шлях методу; порожній шлях методу дає шлях класу, обидва порожні — `/` |
10 + | Назва | `ufo_rest_api_` + назва класу + `_` + назва методу |
11 + | Назва класу | `name` з атрибута класу; без нього — псевдонім процедури з [`#[RPC\Info]`](/docs/api/json-rpc-bundle/add_rpc_service/info) у snake_case (`shopItems` → `shop_items`) |
12 + | Назва методу | `name` з атрибута методу; без нього — назва PHP-методу в snake_case (`createItem` → `create_item`) |
13 + | HTTP-методи | `methods` з атрибута методу; без них — `POST` |
14 + | Інші параметри `#[Route]` | `requirements`, `defaults`, `host` тощо не використовуються: читаються лише `path`, `name` і `methods` |
15 +
16 + ```php
17 + #[RPC\Info('catalog')]
18 + #[Route('/catalog', name: 'catalog')]
19 + class CatalogApi implements IRpcService
20 + {
21 + #[Route('/items/{id}', name: 'item', methods: ['GET'])] // GET /rest/catalog/items/{id}
22 + public function item(int $id): array {}
23 +
24 + #[Route('/items')] // POST /rest/catalog/items
25 + public function createItem(string $title): array {}
26 + }
27 + ```
28 +
29 + Змінні шляху (`{id}`) передаються в метод як параметри з тією самою назвою — див. [Параметри запиту](/docs/api/rest-bundle/requests).
30 +
31 + :::warning
32 + Шлях не виводиться з назви RPC-методу автоматично: без `#[Route]` метод недоступний через REST, а невідомий шлях повертає `404`.
33 + :::
34 +
35 + ## Згенеровані маршрути
36 +
37 + Для кожного REST-методу і версії API створюються два маршрути Symfony:
38 +
39 + | Маршрут | Шлях | HTTP-методи | Призначення |
40 + | --- | --- | --- | --- |
41 + | `<назва>_<версія>` | `<шлях>`, для версій, відмінних від `v1`, — `/<версія><шлях>` | з атрибута | Виклик методу |
42 + | `<назва>_<версія>_method_not_allowed` | той самий | будь-які | Пріоритет `-10`: неправильний HTTP-метод отримує `405`, а не `404` |
43 +
44 + Маршрути з `config/router.yaml` бандла:
45 +
46 + | Маршрут | Шлях | Призначення |
47 + | --- | --- | --- |
48 + | `ufo_rest_doc` | префікс імпорту | OpenAPI, `GET` |
49 + | `ufo_rest_doc_ver` | `/{ver}` (`v\d+`) | OpenAPI для версії |
50 + | `ufo_rest_doc_postman` | `/postman` | Postman |
51 + | `ufo_rest_doc_postman_ver` | `/{ver}/postman` | Postman для версії |
52 + | `ufo_rest_api_entrypoint` | `/{path}` | Загальний вхід, пріоритет `-100`: невідомий шлях повертає `404` у форматі [помилок](/docs/api/rest-bundle/error_handling) |
53 + | `ufo_rest_api_entrypoint_ver` | `/{ver}/{path}` | Те саме для версій, пріоритет `-90` |
54 +
55 + `HEAD` обробляється маршрутами `GET`. `OPTIONS` окремо не обробляється: для методу без `OPTIONS` у `methods` відповідь — `405`.
56 +
57 + ## Версії
58 +
59 + Версії задає JsonRpcBundle: `#[RPC\Info(version: 2, removedMethods: [...])]` ([Версії API](/docs/api/json-rpc-bundle/functionality/versions)). Процедура версії 2 успадковує методи версії 1, які не перевизначає і не прибирає.
60 +
61 + | Версія | Виклик | Документація | Назва маршруту |
62 + | --- | --- | --- | --- |
63 + | `v1` (за замовчуванням) | `/rest/catalog/items/1` | `/rest`, `/rest/postman` | `..._v1` |
64 + | `v2` | `/rest/v2/catalog/items/1` | `/rest/v2`, `/rest/v2/postman` | `..._v2` |
65 +
66 + Невідома версія повертає `404`.
67 +
68 + ## Групи API та кілька входів
69 +
70 + Імпортуйте `config/router.yaml` окремо для кожного входу. `defaults.api_group` вибирає [групу API](/docs/api/json-rpc-bundle/functionality/groups); без нього група — `general`. Префікс URL від назви групи не залежить.
71 +
72 + ```yaml
73 + # config/routes/ufo_rest_api.yaml
74 + rest:
75 + resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
76 + prefix: /rest
77 + trailing_slash_on_root: false
78 +
79 + rest_internal:
80 + resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
81 + prefix: /internal
82 + defaults: { api_group: internal }
83 + trailing_slash_on_root: false
84 +
85 + rest_partners:
86 + resource: ../../vendor/ufo-tech/rest-bundle/config/router.yaml
87 + prefix: /partners
88 + name_prefix: partners_
89 + defaults: { api_group: internal }
90 + trailing_slash_on_root: false
91 + ```
92 +
93 + ```php
94 + #[RPC\Info('catalog')]
95 + #[RPC\APIGroups(['internal', 'public'], false)]
96 + #[Route('/catalog', name: 'catalog')]
97 + class CatalogApi implements IRpcService
98 + {
99 + #[Route('/list', name: 'list', methods: ['GET'])]
100 + public function list(): array { return []; }
101 +
102 + #[RPC\APIGroups(['internal'], false)]
103 + #[Route('/price', name: 'price', methods: ['POST'])]
104 + public function price(int $price): int { return $price; }
105 + }
106 + ```
107 +
108 + * Належність методу до груп визначає `#[RPC\APIGroups]`: атрибут методу замінює атрибут класу, `withDefault: true` додає `general`. `#[RPC\IgnoreApi]` повністю виключає метод. Щоб метод з'явився в REST, `#[Route]` потрібен однаково.
109 + * Кожен вхід має власні методи, версії, документацію і провайдер токенів.
110 + * Назви маршрутів отримують префікс групи: `internal_ufo_rest_doc`, `internal_ufo_rest_api_catalog_list_v1`. `name_prefix` іде після нього: `internal_partners_ufo_rest_doc`.
111 + * Маршрути групи `general` зберігають і старі назви як псевдоніми: `ufo_rest_doc` → `general_ufo_rest_doc`.
112 + * Групу визначає лише маршрут: поле `api_group` у query чи тілі запиту її не змінює.
113 +
114 + ## Поруч з RPC та іншими адаптерами
115 +
116 + Маршрути REST реєструються через `Ufo\JsonRpcBundle\Routing\IApiRouteImport` (клас `RestRouteImport`), тож обробку груп і назв виконує завантажувач маршрутів JsonRpcBundle. RPC-, REST- і маршрути інших адаптерів, що реалізують той самий інтерфейс, можна імпортувати для тих самих груп в одному файлі без конфліктів назв.
117 +
118 + :::info
119 + У 1.1–1.2 для цього використовувався власний завантажувач `RestYamlFileLoader`; у 1.3 його видалено (див. [Історію змін](/docs/api/rest-bundle/change_log)). Застосунків, що лише імпортують `config/router.yaml`, це не стосується.
120 + :::
121 +
122 + ## Діагностика
123 +
124 + * **Методу немає в REST** — перевірте `#[Route]` на методі, групу API імпорту, `#[RPC\IgnoreApi]` і `removedMethods` версії.
125 + * **`405` для наявного методу** — HTTP-методу немає в `methods` атрибута (за замовчуванням — лише `POST`).
126 + * **Назви маршрутів** — `bin/console debug:router | grep ufo_rest`.