This bundle provide an easy way to implement json-rpc server with fully specification supporting. Bundle supports multiple procedure calls in one request as described in specification.
JSON-RPC specification is fully compatible with CQRS architecture
composer require mops1k/json-rpc-bundle
Import route declaration in your routes:
#config/routes/json-rpc.yaml
app_file:
# loads routes from the given routing file stored in some bundle
resource: '@JsonRpcBundle/Resources/config/routing/json-rpc-bundle.yaml'
Or add your own paths by template:
json_rpc_entrypoint:
path: '/path/to/rpc'
methods: 'POST'
controller: 'JsonRpcBundle\Controller\JsonRpcController'
json_rpc_namespace_entrypoint:
path: '/path/to/rpc/{namespace}'
methods: 'POST'
controller: 'JsonRpcBundle\Controller\JsonRpcController'
To create method you have to create invokable class with
attribute \JsonRpcBundle\Attribute\AsRpcMethod
, where methodName
constructor
parameter must contain method name. Example:
<?php
use JsonRpcBundle\Attribute\AsRpcMethod;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
#[AsRpcMethod('methodWithoutContract')]
class MethodWithoutContract
{
public function __invoke(int $id): int
{
return $id;
}
}
Bundle provide possibility to provide params to your DTO class. For these feature you have to add
attribute \JsonRpcBundle\Attribute\RpcMethodContract
.
DTO passed supports validation through symfony/validator.
Example:
<?php
use JsonRpcBundle\Attribute\AsRpcMethod;
use JsonRpcBundle\Attribute\RpcMethodContract;
use JsonRpcBundle\Tests\Stubs\Contract\Contract;
use Symfony\Component\Validator\Constraints as Assert;
readonly class Contract
{
public function __construct(
#[Assert\GreaterThanOrEqual(0)]
public int $id,
#[Assert\NotBlank(allowNull: false)]
public ?string $text = null,
) {
}
}
#[AsRpcMethod('methodWithContract')]
#[RpcMethodContract(Contract::class)]
class MethodWithContract
{
public function __invoke(Contract $contract): array
{
return [
'id' => $contract->id,
'text' => $contract->text,
];
}
}
If you don't want to use DTO, you still able to validate method parameters and set its groups. In this case you need to
implement your method class
from \JsonRpcBundle\MethodResolver\ValidateMethodParametersInterface
.
Example:
<?php
use JsonRpcBundle\Attribute\AsRpcMethod;
use JsonRpcBundle\MethodResolver\ValidateMethodParametersInterface;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\GroupSequence;
#[AsRpcMethod('methodWithoutContract')]
class MethodWithoutContract implements ValidateMethodParametersInterface
{
public function __invoke(int $id): int
{
return $id;
}
public function configureValidation(): Collection
{
return new Collection([
'id' => [
new GreaterThanOrEqual(0),
],
], groups: ['rpc']);
}
public function validationGroups(): array|string|GroupSequence|null
{
return ['rpc'];
}
}
Json rpc supports notification requests what does not return any response. To make your method as notification, just
add void
in __invoke
return type hint.
Example:
use JsonRpcBundle\Attribute\AsRpcMethod;
#[AsRpcMethod('updateUser')]
class UpdateUser
{
public function __invoke(int $id): void
{
// some logic
}
}
Bundle supports method namespacing. To set method namespace, use \JsonRpcBundle\Attribute\AsRpcMethod::$namespace
attribute parameter.
Example:
use JsonRpcBundle\Attribute\AsRpcMethod;
#[AsRpcMethod(methodName: 'update', namespace: 'user')]
class UpdateUser
{
public function __invoke(int $id): void
{
// some logic
}
}
To fetch namespaced method you can call it by method name (namespace.methodName
) or call to path /rpc/{namespace}
and use regular method name.
Examples:
- Call to
/rpc
:{ "jsonrpc": "2.0", "method": "user.update", "params": null, "id": 32 }
- Call to
/rpc/user
:{ "jsonrpc": "2.0", "method": "update", "params": null, "id": 32 }
This feature also supports bath requests.
Bundle supports documentation semi-auto generation
thru nelmio/api-doc-bundle.
By default documentation generate params from method parameters, method contract. If you need more specific params
documentation,
just use OA\Property
attribute. If you need specific response result, then
use \JsonRpcBundle\ApiDoc\Attribute\Result
attribute (set array of OA\Property
inside $properties
parameter).
Object responses auto-generated to documentation by it's describing inside class.