mops1k / json-rpc-bundle
This bundle provide an easy way to implement json-rpc server with fully specification supporting.
Installs: 6
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=8.3
- symfony/framework-bundle: ^6.4 || ^7.0
- symfony/property-access: ^6.4 || ^7.0
- symfony/serializer: ^6.4 || ^7.0
- symfony/validator: ^6.4 || ^7.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.42
- laravel/pint: 1.13.11
- nelmio/api-doc-bundle: 4.29.0
- php-openapi/openapi: ^2.0
- phpunit/phpunit: 10.5.21
- psalm/plugin-phpunit: 0.19.0
- psalm/plugin-symfony: 5.2.3
- vimeo/psalm: 5.16.0
- zircote/swagger-php: 4.10.6
Suggests
- nelmio/api-doc-bundle: ^4.29
README
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
Install
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'
Usage
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; } }
Contract request DTO
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, ]; } }
Validation for method params without contract
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']; } }
Notification
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 } }
Namespace
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.
API Documentation
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.