rpc.request
Event name
rpc.request
Constant
RpcEvent::REQUEST
Class
RpcRequestEvent
Properties
RpcRequest $rpcRequest
Built-in listeners
none
The first RPC event of a request: dispatched after JSON parsing and the token and jsonrpc version checks, but before the cache check and the method call.
When it is dispatched
- Single HTTP request and console call — once.
- Batch: for each item. In process mode — in the child process, not in the parent.
- Notifications and
$rpc.callback— once on receipt; it is not dispatched again during deferred execution of the method. - Calls via
RpcExecutor(REST and MCP adapters) — for each request.
Not dispatched for messages from Symfony Messenger, for cache warm-up requests and for requests rejected earlier (invalid JSON, token error).
What can be changed
- Assigning a new
$event->rpcRequesthas no effect — the handler works with its own reference to the request. - The request object itself can be modified.
$event->rpcRequest->setError($exception)makes the request fail before the method is called (checked onrpc.pre_execute). This does not affect a cached response or the receipt of notifications/callback. - An exception from a listener returns an error to the client.
Usage examples
Tracing
Bind the request to a tracing ID — rayId from the special parameters or a custom header:
#[AsEventListener(RpcEvent::REQUEST)]
final class TraceListener
{
public function __construct(private LoggerInterface $logger) {}
public function __invoke(RpcRequestEvent $event): void
{
$request = $event->rpcRequest;
$this->logger->info('rpc.request', [
'method' => $request->getMethod(),
'id' => $request instanceof RpcNotificationRequest ? null : $request->getId(),
'ray_id' => $request->getRpcParams()?->getRayId(),
'version' => $request->apiVersion,
]);
}
}
Maintenance
Temporarily reject calls to specific methods (for example, during a migration):
#[AsEventListener(RpcEvent::REQUEST)]
final class MaintenanceListener
{
public function __construct(private FeatureFlags $flags) {}
public function __invoke(RpcRequestEvent $event): void
{
if ($this->flags->isFrozen($event->rpcRequest->getMethod())) {
$event->rpcRequest->setError(new RpcLogicException('Method is temporarily unavailable'));
}
}
}
Other ideas
- a method call counter (per-client rate limiting);
- collecting usage statistics for deprecated methods;
- checking additional access conditions for a method (role, client plan).