docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/json-rpc-bundle/config/README.md
new file +220
−0
Bundle configuration
This page describes version 10.x. Configuration for earlier versions is available in the version selector at the top of the page.
All configuration lives in config/packages/ufo_json_rpc.yaml. No section is required: if a section is omitted, the default values apply.
# config/packages/ufo_json_rpc.yaml
ufo_json_rpc:
batch:
enabled: true
process: true
process_count: 2
notification:
process: false
process_count: 2
translations:
paths: []
cache:
ttl: 60
prefix: 'rpc_cache'
# pool: 'cache.app'
security:
protected_api: true
protected_doc: false
token_name: 'Ufo-RPC-Token'
clients_tokens:
- '%env(resolve:UFO_API_TOKEN)%'
# providers: ...
docs:
project_name: 'My Project'
project_description: ''
project_version: null
async_dsn_info: false
validations:
symfony_asserts: false
async: []
The security block
Protects the API with an access key (token) passed in an HTTP header.
| Parameter | Type | Default | Description |
|---|---|---|---|
protected_api |
bool |
true |
Check the token for RPC requests (HTTP, CLI, async) |
protected_doc |
bool |
false |
Check the token for documentation GET requests |
token_name |
string |
Ufo-RPC-Token |
Name of the header carrying the token. In the console, it is the --<token_name in lowercase> option |
clients_tokens |
string[] |
[] |
List of valid tokens for the base validator |
providers |
map |
— | Separate validators for API groups |
ufo_json_rpc:
security:
protected_api: true
protected_doc: false
token_name: 'Ufo-RPC-Token'
clients_tokens:
- '%env(resolve:UFO_API_TOKEN)%'
- '%env(resolve:UFO_API_TOKEN_OLD)%' # multiple keys, for rotation
<include>(.http_headers.md)
Pass tokens via environment variables (.env.local, Symfony secrets) instead of hardcoding them in YAML.
A missing token returns error -32401 (HTTP 401), an invalid one returns -32403.
Custom token validator
If a token list does not fit your case (for example, the token is a user key stored in the database), implement Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator and register it as the base validator:
use Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
use Ufo\RpcError\RpcInvalidTokenException;
final class UserTokenValidator implements ITokenValidator
{
public function __construct(private ApiKeyRepository $keys) {}
public function isValid(string $token): true
{
if (!$this->keys->isActive($token)) {
throw new RpcInvalidTokenException();
}
return true;
}
}
# config/services.yaml
services:
Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator:
alias: App\Security\UserTokenValidator
The validator checks all protected entry points that have no dedicated provider assigned, including the documentation when protected_doc: true.
Providers for API groups (providers)
Each provider sets exactly one of service (a service implementing ITokenValidator) or clients_tokens (a separate list of keys), plus a non-empty api_groups:
ufo_json_rpc:
security:
clients_tokens:
- '%env(resolve:UFO_API_TOKEN)%'
providers:
internal:
api_groups: [internal]
clients_tokens:
- '%env(resolve:UFO_INTERNAL_API_TOKEN)%'
public:
service: App\Security\UserTokenValidator
api_groups: [public]
Groups without a provider are checked by the base validator. See API groups for details.
The docs block
Parameters of the OpenRPC document.
| Parameter | Default | Description |
|---|---|---|
project_name |
My Project |
API name in the documentation and the Postman collection |
project_description |
'' |
API description |
project_version |
null |
Version of your project (not to be confused with API versions) |
async_dsn_info |
false |
Show the parameters of asynchronous transports in the documentation (x-ufo.transport) |
validations.symfony_asserts |
false |
Add the list of Symfony constraints to parameters (x-ufo-assertions) |
The cache block
Response cache for methods with #[RPC\Cache] and the documentation cache.
| Parameter | Default | Description |
|---|---|---|
ttl |
60 |
Default entry lifetime, in seconds |
prefix |
rpc_cache |
Cache namespace |
pool |
null |
Cache pool service to use instead of the local file pool rpc.cache.pool |
ufo_json_rpc:
cache:
pool: 'cache.app' # e.g. a shared Redis
ttl and prefix apply only to the default pool. On multiple servers, use a shared pool so that #[RPC\CacheRelation] invalidation works on all of them.
The batch block
Processing of batch requests.
| Parameter | Default | Description |
|---|---|---|
enabled |
true |
false: batch requests are rejected with a single -32600 error |
process |
true |
true: each item runs in its own ufo:rpc:process child process (isolation and parallelism); false: items run one by one in the current process (inline) |
process_count |
2 |
How many child processes run concurrently (1–10) |
For short methods, inline mode (process: false) is roughly 250 times faster than process mode.
The notification block
Execution of notifications and $rpc.callback.
| Parameter | Default | Description |
|---|---|---|
process |
false |
true: run in a detached ufo:rpc:process process instead of the HTTP worker |
process_count |
2 |
Detached processes running concurrently (1–10); when all are busy, execution happens inline |
Enable notification.process only for rare long-running notifications: each detached process boots the Symfony kernel (~200–300 ms CPU), so under load this is slower than regular execution.
The translations block
Translations of method names and descriptions for the documentation live in the application's translations/rpc.<locale>.yaml. paths adds directories with the same structure, for example from extensions:
ufo_json_rpc:
translations:
paths:
- '%kernel.project_dir%/vendor/acme/rpc-extension/translations'
See API documentation for details.
The async block
List of asynchronous transports. Each item has a type and an arbitrary config (name, dsn and additional keys):
ufo_json_rpc:
async:
- type: 'amqp'
config:
name: 'rpc_async'
dsn: '%env(resolve:RPC_TRANSPORT_DSN)%'
- type: 'mercure'
config:
name: 'rpc_socket'
dsn: '%env(resolve:MERCURE_PUBLIC_URL)%'
topics_prefix: 'rpc.event.'
Items with type: amqp are registered as Symfony Messenger transports named name. See Asynchronous processing for details.
en/docs/api/json-rpc-bundle/config/.http_headers.md
new file +11
−0
HTTP header naming requirements
HTTP header names are not strictly regulated with respect to capitalization, because HTTP headers are case-insensitive. However, there are some common practices and standards that are usually followed for better readability and consistency:
- Capitalization: HTTP header names are usually written in CamelCase, where each word starts with a capital letter, e.g. Content-Type, User-Agent, Accept-Encoding. This does not affect how headers are processed technically, but makes them easier to read.
- Uniqueness: Each header must have a unique name within a single HTTP request or response. The same name cannot be used for different headers in the same request or response.
- Special headers: Some headers are used specifically to control caching behavior (Cache-Control), security (Strict-Transport-Security), authentication (Authorization), etc.
- RFC norms: Header requirements are governed by RFC documents, which define the standards for Internet protocols. For example, general headers and their usage are described in RFC 7231.