rpc.request

← rpc.request

Ashterix

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

en/docs/api/json-rpc-bundle/functionality/events/request.md new file +113 −0

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->rpcRequest has 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 on rpc.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).