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
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.
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.