insidestyles / json-rpc-bundle
A simple and fast way to create json rpc server api as microservice. Json Rpc 2.0 Bundle
Installs: 497
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 2
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=8.1
- ext-json: *
- doctrine/annotations: ^1.6
- laminas/laminas-dependency-plugin: ^2.1
- laminas/laminas-json-server: ^3.3
- symfony/framework-bundle: ^5.4 || ^6.0
Requires (Dev)
- jms/serializer-bundle: ^4.0
- ocramius/proxy-manager: ^2.11
- phpunit/phpunit: >=6.5
- symfony/messenger: ^5.4 || ^6.0
- symfony/serializer: ^5.4 || ^6.0
- symfony/validator: ^5.4 || ^6.0
Suggests
- doctrine/annotations: Install for annotation features
- jms/serializer-bundle: Allows JMS Serializer
- ocramius/proxy-manager: Use ocramius/proxy-manager for remote service call
- symfony/messenger: Use Symfony Messenger
- symfony/serializer: Allows Symfony Serializer
- symfony/validator: Use Symfony Validator for message bus validation
README
Symfony Json Rpc Bundle Fast way to create json rpc microservice, using symfony messenger and laminas json server
- Json Rpc 2.0
- Batch Support
Requirements
"php": ">=8.0",
"ext-json": "*",
"symfony/framework-bundle": "^5.3" || ^6.0,
"laminas/laminas-json-server": "^3.1"
Installation
This package is installable and autoloadable via Composer
composer require insidestyles/json-rpc-bundle
Add package config: json_rpc_api.yaml
json_rpc_api: handlers: main: path: /api host: ~ serializer: ~ context: ~ logger: ~ error_handler: ~
Add Bundle to App
Insidestyles\JsonRpcBundle\JsonRpcBundle::class => ['all' => true],
Add route config: json_rpc_api_routing.yaml
_json_rpc_api: resource: . type: json_rpc_api
Usage
- Add Example HelloWorldApi
Update api interface with JsonRpcApi Annotation
@JsonRpcApi(namespace = "main")
<?php /** * @JsonRpcApi(namespace = "main") * * @author Fuong <insidestyles@gmail.com> */ interface HelloWordJsonRpcApiInterface extends JsonRpcApiInterface { public function helloWorld(string $name); }
- HelloWorld Api with Symfony Messenger:
Add requirement:
composer require symfony/messenger
Config Symfony Messenger https://symfony.com/doc/current/messenger.html
services: hello_world_api: class: Insidestyles\JsonRpcBundle\Api\MessageBus\HelloWorldApi arguments: - "@messenger.bus.default" tags: - {name: json_rpc_api, handler: main} hello_world_api_handler: class: Insidestyles\JsonRpcBundle\Handler\HelloWorldHandler tags: - {name: messenger.message_handler}
- Add extra api endpoint with jms serializer and default symfony logger
json_rpc_api: handlers: main: path: /api host: ~ serializer: ~ context: ~ logger: ~ error_handler: ~ auth: path: /auth host: ~ serializer: json_rpc_api.serialzier.jms context: ~ logger: monolog.logger error_handler: ~
- Add custom serializer adapter
composer require jms/serializer-bundle
services: json_rpc_api.serialzier.custom: class: Insidestyles\JsonRpcBundle\Server\Adapter\Serializer\CustomSerializer arguments: - "@serializer"
- Add custom serializer adapter
services: Insidestyles\\Core\\Exceptions\\ApiErrorHandler: class: 'Insidestyles\Core\Exceptions\ApiErrorHandler' tags: - { name: 'json_rpc_api.error_handler' }
<?php namespace Insidestyles\Core\Exceptions; use Doctrine\ORM\EntityNotFoundException; use Insidestyles\JsonRpcBundle\Server\ErrorHandler\Handler\ErrorHandlerInterface; use Throwable; class ApiErrorHandler implements ErrorHandlerInterface { private const SYSTEM_ERRORS = [ EntityNotFoundException::class, ]; public function parse(Throwable $e): array { if (!$this->isSupported($e)) { return []; } return [ 'code' => $e->getCode(), 'message' => $e->getMessage(), 'data' => [], ]; } public function isSupported(Throwable $e): bool { return $e instanceof IsExceptionInterface || in_array(get_class($e), static::SYSTEM_ERRORS); } }
- Enable jms serializer
json_rpc_api: handlers: main: path: /api host: ~ serializer: json_rpc_api.serializer.jms context: json_rpc_api.serializer.default_context logger: ~ error_handler: ~
Tips
- Install Symfony Validator and validation middle ware from messenger bus for message validation
framework: messenger: buses: command_bus: middleware: - messenger.middleware.validation
<?php namespace Insidestyles\JsonRpcBundle\Message; use Symfony\Component\Validator\Constraints as Assert; /** * @author Fuong <insidestyles@gmail.com> */ class HelloWorldMessage { /** * @Assert\NotBlank() * @var string */ private $message; public function __construct(string $message) { $this->message = $message; } /** * @return string */ public function getMessage(): string { return $this->message; } }
-
You don't have to extend class AbstractApi if you don't want to use Symfony Messenger. Just implement your own interface that extends JsonRpcApiInterface. See example HelloWorldApi
-
Go to api endpoint http:://localhost/api to see json-rpc methods
-
simple request content
{ "id": 1, "method": "main.helloWorld", "params": { "name": "test" } }
- batch request content
[ { "id": 1, "method": "main.helloWorld", "params": { "name": "hello1" } }, { "id": 2, "method": "main.helloWorld", "params": { "name": "hello2" } } ]
- using remote service with other api endpoints
Add requirement:
composer ocramius/proxy-manager
Update service
hello.remote_services.hello: tags: - name: 'json_rpc_remote_service' url: '%hello.api_server_url%' class: Insidestyles\JsonRpcBundle\Sdk\Contract\HelloWordJsonRpcApiInterface
Now you can call api
$container->get('hello.remote_services.hello')->helloWorld('Hi');