Життєвий цикл запиту

← Життєвий цикл запиту

Ashterix

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

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

1 + # Життєвий цикл запиту
2 +
3 + Як REST Bundle обробляє запит — від HTTP-запиту до RPC-виклику і назад. Опис відповідає версії 1.3; як той самий виклик обробляє ядро, — на сторінці [Життєвий цикл JsonRpcBundle](/docs/api/json-rpc-bundle/developers/lifecycle).
4 +
5 + ## REST-виклик
6 +
7 + 1. **`kernel.request`, пріоритет 32 — `RouterListener`** знаходить згенерований REST-маршрут. Його defaults містять `_rest_route` (назва REST-маршруту без версії), `_ver` для версій, відмінних від `v1`, `api_group` і `_rest_name_prefix`.
8 + 2. **`kernel.request`, пріоритет 30 — `RestControllerListener`** записує групу в `ApiGroupContext` і для REST-виклику спрямовує `_controller` на `RestEntryPointController::rest` з атрибутами `rpcRoute` і `ver`.
9 + 3. **`RestRequestParser::parse()`**
10 + * знаходить REST-маршрут і RPC `Service` для групи та версії (`404`, якщо немає);
11 + * перевіряє HTTP-метод: `HEAD` вважається `GET`, недозволений метод — `405`;
12 + * скидає пул RPC-подій (`RpcEventFactory::reset()`), встановлює `HttpTokenHolder` і carrier `RpcFromRest`, перевіряє токен (`protected_api`).
13 + 4. **`RpcFromRest`** будує `RpcRequest`: згенерований `id`, назва RPC-методу, об'єднані [параметри](/docs/api/rest-bundle/requests) і `apiVersion`.
14 + 5. **`RpcExecutor::execute()`** виконує запит так само, як JSON-RPC: `rpc.request` → `rpc.pre_execute` (формування аргументів, валідація, конвертація, `#[RPC\Lock]`, виклик методу) → `rpc.pre_response` → `rpc.post_execute`. Будь-яка помилка проходить через `rpc.error` і стає відповіддю з помилкою.
15 + 6. **Контролер** повертає `200` з результатом методу або перетворює помилку на [RFC 9457 problem](/docs/api/rest-bundle/error_handling) через `RestErrorNormalizer`.
16 + 7. **`kernel.terminate`** — для успішного виклику генерується `rpc.post_response` (інвалідація `#[RPC\CacheRelation]`, post-response лістенери). Для помилки — ні.
17 +
18 + Запит без відповідного REST-маршруту потрапляє в загальний вхід `ufo_rest_api_entrypoint` (пріоритет `-100`), і парсер повертає `404`. Запит з неправильним HTTP-методом потрапляє в маршрут `<назва>_method_not_allowed` (пріоритет `-10`), і парсер повертає `405`.
19 +
20 + ## Документація
21 +
22 + 1. Пріоритет 32 — роутинг на маршрут з default `_rest_doc`.
23 + 2. Пріоритет 30 — `RestControllerListener` записує групу в `ApiGroupContext`.
24 + 3. Пріоритет 8 — `RestDocLocaleListener` вибирає мову з `Accept-Language` (`RpcLocaleNegotiator::applyLocale()`).
25 + 4. `RestEntryPointController::openapiAction()` / `postmanAction()` перевіряє токен (`protected_doc`) і будує документ для версії та групи.
26 + 5. `kernel.response` — `Content-Language` і `Vary: Accept-Language`.
27 +
28 + RPC-події на цьому шляху не генеруються; документ будується на кожен запит.
29 +
30 + ## Події
31 +
32 + REST-виклик генерує ті самі події, що й JSON-RPC, тож лістенери застосунку працюють для обох:
33 +
34 + | Подія | Константа | Коли |
35 + | --- | --- | --- |
36 + | `rpc.request` | `RpcEvent::REQUEST` | запит прийнято |
37 + | `rpc.pre_execute` | `RpcEvent::PRE_EXECUTE` | перед методом |
38 + | `rpc.pre_response` | `RpcEvent::PRE_RESPONSE` | відповідь сформовано |
39 + | `rpc.post_execute` | `RpcEvent::POST_EXECUTE` | після методу |
40 + | `rpc.error` | `RpcEvent::ERROR` | будь-яка помилка |
41 + | `rpc.post_response` | `RpcEvent::POST_RESPONSE` | на `kernel.terminate`, після успішного виклику |
42 +
43 + Детально про кожну подію — у розділі [Події життєвого циклу](/docs/api/json-rpc-bundle/functionality/events).
44 +
45 + :::info
46 + До 1.3 REST-контролер виконував запит через `RpcRequestHandler` без `RpcExecutor`, і `rpc.post_response` для REST не генерувався.
47 + :::
48 +
49 + ## Стан між запитами
50 +
51 + Група API зберігається в `ApiGroupContext`, carrier — у `RequestCarrier`, токен-холдер — в `IRpcSecurity`; ці сервіси належать JsonRpcBundle і скидаються між запитами в довгоживучих воркерах. `RestServiceMap` будує REST-маршрути для групи один раз і перемикається між уже побудованими мапами, коли змінюється група в `ApiGroupContext`.