Skip to content

Commit 3b9ddd0

Browse files
authored
Add doc and improve behat tests (#17)
Fix #16
1 parent 014bac6 commit 3b9ddd0

File tree

12 files changed

+311
-158
lines changed

12 files changed

+311
-158
lines changed

README.md

+151-145
Original file line numberDiff line numberDiff line change
@@ -11,158 +11,164 @@ Symfony JSON-RPC HTTP Server to convert an HTTP json-rpc request into HTTP json-
1111

1212
## How to use
1313

14-
Sdk requires only two things :
15-
- A method resolver : must implement [MethodResolverInterface](./src/Domain/Model/MethodResolverInterface.php), resolving logic's is your own.
16-
- Methods : JsonRpc methods that implement [JsonRpcMethodInterface](./src/Domain/Model/JsonRpcMethodInterface.php)
17-
18-
:warning: No dependency injection is managed in this library
19-
20-
### Example
21-
#### JSON-RPC Method
22-
```php
23-
use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface;
24-
25-
class DummyMethod implements JsonRpcMethodInterface
26-
{
27-
/**
28-
* @param array $paramList
29-
*
30-
* @throws \Exception
31-
*/
32-
public function validateParams(array $paramList)
33-
{
34-
//If case your app require a specific param for instance
35-
if (!isset($paramList['my-required-key')) {
36-
throw new \Exception('"my-required-key" is a required key');
37-
}
38-
}
39-
40-
/**
41-
* @param array|null $paramList
42-
*
43-
* @return array|int|null
44-
*/
45-
public function apply(array $paramList = null)
46-
{
47-
// Handle the request
48-
...
49-
// Then return a result
50-
return [
51-
'status' => 'done',
52-
];
53-
// Or
54-
return null;
55-
// Or
56-
return 12345;
57-
}
58-
}
59-
```
60-
#### Array method resolver (simple example)
61-
*You could take example on [the one used for behat tests](./features/bootstrap/App/BehatMethodResolver.php)*
62-
```php
63-
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcMethodNotFoundException;
64-
use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface;
65-
use Yoanm\JsonRpcServer\Domain\Model\MethodResolverInterface;
66-
67-
class ArrayMethodResolver implements MethodResolverInterface
68-
{
69-
/** @var JsonRpcMethodInterface[] */
70-
private $methodList = [];
71-
72-
/**
73-
* @param string $methodName
74-
*
75-
* @return JsonRpcMethodInterface
76-
*
77-
* @throws JsonRpcMethodNotFoundException
78-
*/
79-
public function resolve(string $methodName) : JsonRpcMethodInterface
80-
{
81-
if (!isset($this->methodList[$methodName])) {
82-
throw new JsonRpcMethodNotFoundException($methodName);
83-
}
84-
85-
return $this->methodList[$methodName];
86-
}
87-
88-
/**
89-
* @param JsonRpcMethodInterface $method
90-
* @param string $methodName
91-
*/
92-
public function addMethod(JsonRpcMethodInterface $method, string $methodName)
93-
{
94-
$this->methodList[$methodName] = $method;
95-
}
96-
}
97-
```
14+
You can either use this library as a simple extension or like any symfony bundle.
9815

99-
Then add your method to the resolver and create the endpoint :
100-
```php
101-
use Yoanm\JsonRpcServer\App\Creator\CustomExceptionCreator;
102-
use Yoanm\JsonRpcServer\App\Creator\ResponseCreator;
103-
use Yoanm\JsonRpcServer\App\Manager\MethodManager;
104-
use Yoanm\JsonRpcServer\App\RequestHandler;
105-
use Yoanm\JsonRpcServer\App\Serialization\RequestDenormalizer;
106-
use Yoanm\JsonRpcServer\App\Serialization\ResponseNormalizer;
107-
use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint;
108-
use Yoanm\JsonRpcServer\Infra\Serialization\RawRequestSerializer;
109-
use Yoanm\JsonRpcServer\Infra\Serialization\RawResponseSerializer;
110-
111-
$resolver = new ArrayMethodResolver();
112-
$resolver->addMethod(
113-
'dummy-method'
114-
new DummyMethod()
115-
);
116-
117-
$responseCreator = new ResponseCreator();
118-
119-
$endpoint = new JsonRpcEndpoint(
120-
new RawRequestSerializer(
121-
new RequestDenormalizer()
122-
),
123-
new RequestHandler(
124-
new MethodManager(
125-
$resolver,
126-
new CustomExceptionCreator()
127-
),
128-
$responseCreator
129-
),
130-
new RawResponseSerializer(
131-
new ResponseNormalizer()
132-
),
133-
$responseCreator
134-
);
135-
```
16+
*[Behat demo app configuration folders](./features/demo_app/) can be used as examples.*
13617

137-
Once endpoint is ready, you can send it request string :
138-
```php
139-
use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint;
140-
141-
$requestString = <<<JSONRPC
142-
{
143-
"jsonrpc": "2.0",
144-
"id": 1
145-
"method": "dummy-method",
146-
"params": {
147-
"my-required-key": "a-value"
148-
}
149-
}
150-
JSONRPC;
151-
152-
$responseString = $endpoint->index($requestString);
153-
```
18+
### With Symfony bundle
15419

155-
`$responseString` will be the following string depending of method returned value :
156-
* ```json
157-
{"jsonrpc":"2.0","id":1,"result":{"status":"done"}}
20+
- Add the bundles in your `config/bundles.php` file:
21+
```php
22+
// config/bundles.php
23+
return [
24+
...
25+
Yoanm\SymfonyJsonRpcHttpServer\JsonRpcHttpServerBundle::class => ['all' => true],
26+
...
27+
];
15828
```
159-
* ```json
160-
{"jsonrpc":"2.0","id":1,"result":null}
29+
30+
- Add the following in your routing configuration :
31+
```yaml
32+
# config/routes.yaml
33+
json-rpc-endpoint:
34+
resource: '@JsonRpcHttpServerBundle/Resources/config/routing/endpoint.xml'
35+
```
36+
37+
- Add the following in your configuration :
38+
```yaml
39+
# config/config.yaml
40+
json_rpc_http_server: ~
16141
```
16242
163-
* ```json
164-
{"jsonrpc":"2.0","id":1,"result":12345}
43+
### With Symfony extension only
44+
- Load the extension in your kernel :
45+
```php
46+
// src/Kernel.php
47+
...
48+
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
49+
use Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension;
50+
...
51+
class Kernel
52+
{
53+
use MicroKernelTrait;
54+
....
55+
/**
56+
* {@inheritdoc}
57+
*/
58+
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
59+
{
60+
/**** Add and load extension **/
61+
$container->registerExtension($extension = new JsonRpcHttpServerExtension());
62+
// If you use Symfony Config component, add "json_rpc_http_server: ~" in your configuration.
63+
// Else load it there
64+
$container->loadFromExtension($extension->getAlias());
65+
66+
...
67+
}
68+
....
69+
}
70+
```
71+
72+
- Map your your JSON-RPC methods, see **JSON-RPC Method mapping** section below
73+
- Manually configure an endpoint, see **Routing** section below
74+
75+
## JSON-RPC Method mapping
76+
You have many ways to inject you json-rpc methods :
77+
- If you use the bundle, you can do it by configuration :
78+
```yaml
79+
# config/config.yaml
80+
json_rpc_http_server:
81+
methods_mapping:
82+
method-a: '@method-a.service-id'
83+
method-b:
84+
service: '@method-b.service-id'
85+
aliases: 'method-b-alias'
86+
method-c:
87+
service: '@method-c.service-id'
88+
aliases: ['method-c-alias-1', 'method-c-alias-2']
89+
```
90+
- You can use tag in the service definition as below :
91+
```yaml
92+
services:
93+
method-a.service-id:
94+
class: Method\A\Class
95+
public: true # <= do no forget the set visibility to public !
96+
tags:
97+
- { name: 'json_rpc_http_server.jsonrpc_method', method: 'method-a' }
98+
- { name: 'json_rpc_http_server.jsonrpc_method', method: 'method-a-alias' }
99+
```
100+
- Inject manually your mapping during container building
101+
```php
102+
// src/Kernel.php
103+
...
104+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
105+
use Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension;
106+
...
107+
class Kernel implements CompilerPassInterface
108+
{
109+
....
110+
/**
111+
* {@inheritdoc}
112+
*/
113+
public function process(ContainerBuilder $container)
114+
{
115+
$container->getDefinition(JsonRpcHttpServerExtension::SERVICE_NAME_RESOLVER_SERVICE_NAME)
116+
->addMethodCall('addMethodMapping', ['method-a', 'method-a.service-id'])
117+
->addMethodCall('addMethodMapping', ['method-b', 'method-b.service-id'])
118+
->addMethodCall('addMethodMapping', ['method-b-alias', 'method-b.service-id'])
119+
;
120+
}
121+
....
122+
}
123+
```
124+
- Or inject manually your mapping after container building
125+
```php
126+
$container->get(JsonRpcHttpServerExtension::SERVICE_NAME_RESOLVER_SERVICE_NAME)
127+
->addMethodMapping('method-a', 'method-a.service-id')
128+
->addMethodMapping('method-b', 'method-b.service-id')
129+
->addMethodMapping('method-b-alias', 'method-b.service-id')
130+
;
165131
```
132+
133+
## Routing
134+
- If you use the bundle, the default endpoint is `/json-rcp`. You can custome it by using :
135+
```yaml
136+
# config/config.yaml
137+
json_rpc_http_server:
138+
http_endpoint_path: '/my-custom-endpoint'
139+
```
140+
141+
- Or you can define your own route and bind the endpoint as below :
142+
```yaml
143+
# config/routes.yaml
144+
index:
145+
path: /my-json-rpc-endpoint
146+
defaults: { _controller: 'json_rpc_http_server.endpoint:index' }
147+
```
148+
149+
## Custom method resolver
150+
151+
By default this bundle use [`yoanm/jsonrpc-server-sdk-psr11-resolver`](https://github.com/yoanm/php-jsonrpc-server-sdk-psr11-resolver).
152+
153+
In case you want to use your own, you can do it by using :
154+
155+
### Service definition tag
156+
Use `json_rpc_http_server.method_resolver` tag as following:
157+
```yaml
158+
services:
159+
my.custom_method_resolver.service:
160+
class: Custom\Method\Resolver\Class
161+
tags: ['json_rpc_http_server.method_resolver']
162+
```
163+
164+
### Bundle configuration
165+
Configure the bundle as below
166+
```yaml
167+
# config/config.yaml
168+
json_rpc_http_server:
169+
method_resolver: '@my.custom_method_resolver.service'
170+
```
171+
 
166172

167173
## Contributing
168174
See [contributing note](./CONTRIBUTING.md)

features/bootstrap/DemoAppContext.php

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use DemoApp\DefaultKernel;
88
use DemoApp\KernelWithBundle;
99
use DemoApp\KernelWithBundleAndCustomResolver;
10+
use DemoApp\KernelWithBundleAndMethodsMapping;
1011
use DemoApp\KernelWithCustomResolver;
1112
use PHPUnit\Framework\Assert;
1213
use Symfony\Component\HttpFoundation\Request;
@@ -23,6 +24,8 @@ class DemoAppContext implements Context
2324
private $useCustomResolver = false;
2425
/** @var bool */
2526
private $useBundle = false;
27+
/** @var bool */
28+
private $useBundleMethodsMappingFromConfiguration = false;
2629

2730
/**
2831
* @Given I use my DemoApp custom method resolver
@@ -40,6 +43,15 @@ public function givenDemoAppWillUseBundle()
4043
$this->useBundle = true;
4144
}
4245

46+
/**
47+
* @Given DemoApp will use JsonRpcHttpServerBundle with methods mapping configuration
48+
*/
49+
public function givenDemoAppWillUseBundleWithMethodsMappingConfiguration()
50+
{
51+
$this->givenDemoAppWillUseBundle();
52+
$this->useBundleMethodsMappingFromConfiguration = true;
53+
}
54+
4355
/**
4456
* @When I send following :httpMethod input on :uri demoApp kernel endpoint:
4557
*/
@@ -77,6 +89,8 @@ protected function getDemoAppKernel()
7789
$env = 'prod';
7890
$debug = true;
7991
switch (true) {
92+
case true === $this->useBundleMethodsMappingFromConfiguration:
93+
return new KernelWithBundleAndMethodsMapping($env, $debug);
8094
case true === $this->useBundle && true === $this->useCustomResolver:
8195
return new KernelWithBundleAndCustomResolver($env, $debug);
8296
case true === $this->useBundle && false === $this->useCustomResolver:

0 commit comments

Comments
 (0)