Extensions

← Extensions

Ashterix

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

en/docs/api/rest-bundle/developers/extensions.md new file +94 āˆ’0

1 + # Extensions
2 +
3 + What can be changed or added in REST Bundle without changing its code. Other packages of the ecosystem are listed on the [JsonRpcBundle Extensions](/docs/api/json-rpc-bundle/developers/extensions) page.
4 +
5 + ## RPC events
6 +
7 + A REST call fires the same [events](/docs/api/json-rpc-bundle/functionality/events) as JSON-RPC (see [Lifecycle](/docs/api/rest-bundle/developers/lifecycle)), so an application listener works for both protocols:
8 +
9 + ```php
10 + use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
11 + use Ufo\JsonRpcBundle\EventDrivenModel\Events\RpcEvent;
12 + use Ufo\JsonRpcBundle\EventDrivenModel\Events\RpcPostResponseEvent;
13 +
14 + #[AsEventListener(event: RpcEvent::POST_RESPONSE)]
15 + final class AuditListener
16 + {
17 + public function __invoke(RpcPostResponseEvent $event): void
18 + {
19 + // $event->rpcRequest->getMethod(), $event->response, $event->service
20 + }
21 + }
22 + ```
23 +
24 + To tell a REST call from a JSON-RPC one, check the carrier: `RequestCarrier::getCarrier() instanceof Ufo\RestBundle\Services\RpcFromRest`.
25 +
26 + ## Replacing the request parser
27 +
28 + The controller depends on `Ufo\RestBundle\Interfaces\RestRequestParserInterface` with a single method `parse(string $routeName, Request $request): Service`. Extend `RestRequestParser` and alias the interface:
29 +
30 + ```yaml
31 + # config/services.yaml
32 + Ufo\RestBundle\Interfaces\RestRequestParserInterface: '@App\Rest\TenantAwareParser'
33 + ```
34 +
35 + ```php
36 + use Symfony\Component\HttpFoundation\Request;
37 + use Ufo\JsonRpcBundle\Server\ServiceMap\Service;
38 + use Ufo\RestBundle\Services\RestRequestParser;
39 +
40 + final class TenantAwareParser extends RestRequestParser
41 + {
42 + public function parse(string $routeName, Request $request): Service
43 + {
44 + // for example, reject a request without a tenant header before the call
45 + return parent::parse($routeName, $request);
46 + }
47 + }
48 + ```
49 +
50 + The parser must leave the carrier in `RequestCarrier`: the controller executes exactly `RequestCarrier::getCarrier()`. Exceptions implementing `Ufo\RestBundle\Exceptions\RestErrorInterface` are returned with a status equal to their code; the rest go through `RestErrorNormalizer`.
51 +
52 + ## Reading the REST map
53 +
54 + `Ufo\RestBundle\Services\RestServiceMap` returns the REST routes and RPC services of the current API group (from `ApiGroupContext`):
55 +
56 + ```php
57 + foreach ($restServiceMap->getVersions() as $version) {
58 + foreach ($restServiceMap->getRoutes($version) as $name => $route) {
59 + $service = $restServiceMap->getService($name, $version); // RPC Service
60 + // $route->getPath(), $route->getMethods()
61 + }
62 + }
63 + ```
64 +
65 + `getRoute()`, `getService()` and the methods called with an unknown version throw `RestResourceNotFoundException`.
66 +
67 + ## Translations from a bundle
68 +
69 + A bundle that provides RPC methods can also provide their titles and descriptions; REST documents pick them up (since 1.3):
70 +
71 + ```php
72 + public function prepend(ContainerBuilder $container): void
73 + {
74 + $container->prependExtensionConfig('ufo_json_rpc', [
75 + 'translations' => ['paths' => [__DIR__.'/../../translations']],
76 + ]);
77 + }
78 + ```
79 +
80 + ## Another adapter alongside REST
81 +
82 + An adapter that imports its own routes file for each API group implements `Ufo\JsonRpcBundle\Routing\IApiRouteImport` (autoconfiguration, tag `ufo.rpc.route_import`), the same as `RestRouteImport`:
83 +
84 + ```php
85 + use Ufo\JsonRpcBundle\Routing\IApiRouteImport;
86 +
87 + final class AcmeRouteImport implements IApiRouteImport
88 + {
89 + public function getResource(): string { return __DIR__.'/../../config/router.yaml'; }
90 + public function getRouteNamePrefixAttribute(): string { return '_acme_name_prefix'; }
91 + }
92 + ```
93 +
94 + Do not extend the JsonRpcBundle route loader for this. A minimal adapter with `RpcExecutor` is described on the [JsonRpcBundle For developers](/docs/api/json-rpc-bundle/developers) page.