docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/rest-bundle/developers/lifecycle.md
new file +51
ā0
1
+
# Request lifecycle
2
+
3
+
How REST Bundle processes a request: from the HTTP request to the RPC call and back. The description matches version 1.3; how the core processes the same call is described on the [JsonRpcBundle lifecycle](/docs/api/json-rpc-bundle/developers/lifecycle) page.
4
+
5
+
## REST call
6
+
7
+
1. **`kernel.request`, priority 32: `RouterListener`** finds the generated REST route. Its defaults contain `_rest_route` (the REST route name without the version), `_ver` for versions other than `v1`, `api_group` and `_rest_name_prefix`.
8
+
2. **`kernel.request`, priority 30: `RestControllerListener`** writes the group to `ApiGroupContext` and, for a REST call, points `_controller` to `RestEntryPointController::rest` with the `rpcRoute` and `ver` attributes.
9
+
3. **`RestRequestParser::parse()`**
10
+
* finds the REST route and the RPC `Service` for the group and version (`404` if missing);
11
+
* checks the HTTP method: `HEAD` counts as `GET`, a method that is not allowed gives `405`;
12
+
* resets the RPC event pool (`RpcEventFactory::reset()`), sets `HttpTokenHolder` and the `RpcFromRest` carrier, checks the token (`protected_api`).
13
+
4. **`RpcFromRest`** builds an `RpcRequest`: a generated `id`, the RPC method name, the merged [parameters](/docs/api/rest-bundle/requests) and `apiVersion`.
14
+
5. **`RpcExecutor::execute()`** executes the request the same way as JSON-RPC: `rpc.request` ā `rpc.pre_execute` (building arguments, validation, conversion, `#[RPC\Lock]`, method call) ā `rpc.pre_response` ā `rpc.post_execute`. Any error goes through `rpc.error` and becomes an error response.
15
+
6. **The controller** returns `200` with the method result or converts the error into an [RFC 9457 problem](/docs/api/rest-bundle/error_handling) via `RestErrorNormalizer`.
16
+
7. **`kernel.terminate`**: `rpc.post_response` fires for a successful call (`#[RPC\CacheRelation]` invalidation, post-response listeners). Not for an error.
17
+
18
+
A request without a matching REST route lands in the catch-all entry point `ufo_rest_api_entrypoint` (priority `-100`), and the parser returns `404`. A request with a wrong HTTP method lands in the `<name>_method_not_allowed` route (priority `-10`), and the parser returns `405`.
19
+
20
+
## Documentation
21
+
22
+
1. Priority 32: routing to a route with the `_rest_doc` default.
23
+
2. Priority 30: `RestControllerListener` writes the group to `ApiGroupContext`.
24
+
3. Priority 8: `RestDocLocaleListener` picks the language from `Accept-Language` (`RpcLocaleNegotiator::applyLocale()`).
25
+
4. `RestEntryPointController::openapiAction()` / `postmanAction()` checks the token (`protected_doc`) and builds the document for the version and group.
26
+
5. `kernel.response`: `Content-Language` and `Vary: Accept-Language`.
27
+
28
+
No RPC events are fired on this path; the document is built on every request.
29
+
30
+
## Events
31
+
32
+
A REST call fires the same events as JSON-RPC, so the application's listeners work for both:
33
+
34
+
| Event | Constant | When |
35
+
| --- | --- | --- |
36
+
| `rpc.request` | `RpcEvent::REQUEST` | the request is accepted |
37
+
| `rpc.pre_execute` | `RpcEvent::PRE_EXECUTE` | before the method |
38
+
| `rpc.pre_response` | `RpcEvent::PRE_RESPONSE` | the response is formed |
39
+
| `rpc.post_execute` | `RpcEvent::POST_EXECUTE` | after the method |
40
+
| `rpc.error` | `RpcEvent::ERROR` | any error |
41
+
| `rpc.post_response` | `RpcEvent::POST_RESPONSE` | on `kernel.terminate`, after a successful call |
42
+
43
+
Each event is described in detail in [Lifecycle events](/docs/api/json-rpc-bundle/functionality/events).
44
+
45
+
:::info
46
+
Before 1.3 the REST controller executed the request through `RpcRequestHandler` without `RpcExecutor`, and `rpc.post_response` was not fired for REST.
47
+
:::
48
+
49
+
## State between requests
50
+
51
+
The API group is kept in `ApiGroupContext`, the carrier in `RequestCarrier`, the token holder in `IRpcSecurity`; these services belong to JsonRpcBundle and are reset between requests in long-running workers. `RestServiceMap` builds the REST routes for a group once and switches between already built maps when the group in `ApiGroupContext` changes.