Skip to content

Commit 864226d

Browse files
authored
Add configurable debug mode (#93)
1 parent 7278083 commit 864226d

File tree

8 files changed

+108
-11
lines changed

8 files changed

+108
-11
lines changed

README.md

+30
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,36 @@ mapping_aware_service:
130130
tags: ['json_rpc_http_server.method_aware']
131131
```
132132
133+
## Debug mode
134+
135+
You can setup 'debug' mode for the JSON-RPC server, which allows display of verbose error information within the response JSON body.
136+
This information contains actual exception class name, code, message and stack trace.
137+
138+
> Note: you should never enable 'debug' mode in 'production' environment, since it will expose vital internal information to the API consumer.
139+
140+
Configuration example:
141+
142+
```yaml
143+
# file 'config/packages/json_rpc.yaml'
144+
json_rpc_http_server:
145+
endpoint: '/json-rpc'
146+
debug:
147+
enabled: false
148+
max_trace_size: 10
149+
show_trace_arguments: true
150+
simplify_trace_arguments: true
151+
152+
when@dev:
153+
json_rpc_http_server:
154+
debug:
155+
enabled: true
156+
157+
when@test:
158+
json_rpc_http_server:
159+
debug:
160+
enabled: true
161+
```
162+
133163
## Contributing
134164
135165
See [contributing note](./CONTRIBUTING.md)

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"symfony/event-dispatcher-contracts": "^1.0 || ^2.0 || ^3.0",
3939
"symfony/http-foundation": "^4.4 || ^5.4 || ^6.0",
4040
"symfony/http-kernel": "^4.4 || ^5.4 || ^6.0",
41-
"yoanm/jsonrpc-server-sdk": "^3.0"
41+
"yoanm/jsonrpc-server-sdk": "^3.3"
4242
},
4343
"require-dev": {
4444
"behat/behat": "^3.9.0",

src/DependencyInjection/Configuration.php

+24
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,30 @@ public function getConfigTreeBuilder()
2222
->treatNullLike(self::DEFAULT_ENDPOINT)
2323
->defaultValue(self::DEFAULT_ENDPOINT)
2424
->end()
25+
->arrayNode('debug')
26+
->addDefaultsIfNotSet()
27+
->children()
28+
->booleanNode('enabled')
29+
->info(
30+
'Whether to render debug information on error or not (should NOT be enabled on prod)'
31+
)
32+
->defaultFalse()
33+
->end()
34+
->integerNode('max_trace_size')
35+
->info('Max debug trace size')
36+
->min(0)
37+
->defaultValue(10)
38+
->end()
39+
->booleanNode('show_trace_arguments')
40+
->info('Whether to render debug stack trace arguments or not')
41+
->defaultValue(true)
42+
->end()
43+
->booleanNode('simplify_trace_arguments')
44+
->info('Whether to simplify representation of debug stack trace arguments or not')
45+
->defaultValue(true)
46+
->end()
47+
->end()
48+
->end()
2549
->end()
2650
;
2751

src/DependencyInjection/JsonRpcHttpServerExtension.php

+18-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Yoanm\JsonRpcServer\Domain\JsonRpcMethodAwareInterface;
1515

1616
/**
17-
* Class JsonRpcHttpServerExtension
17+
* @see \Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\Configuration
1818
*/
1919
class JsonRpcHttpServerExtension implements ExtensionInterface, CompilerPassInterface
2020
{
@@ -66,7 +66,8 @@ public function process(ContainerBuilder $container)
6666
{
6767
$this->bindJsonRpcServerDispatcher($container);
6868
$this->bindValidatorIfDefined($container);
69-
$this->binJsonRpcMethods($container);
69+
$this->bindJsonRpcMethods($container);
70+
$this->bindDebug($container);
7071
}
7172

7273
/**
@@ -102,17 +103,19 @@ private function compileAndProcessConfigurations(array $configs, ContainerBuilde
102103
$configuration = new Configuration();
103104
$config = (new Processor())->processConfiguration($configuration, $configs);
104105

105-
$httpEndpointPath = $config['endpoint'];
106+
$container->setParameter(self::ENDPOINT_PATH_CONTAINER_PARAM_ID, $config['endpoint']);
106107

107-
$container->setParameter(self::ENDPOINT_PATH_CONTAINER_PARAM_ID, $httpEndpointPath);
108+
foreach ($config['debug'] as $name => $value) {
109+
$container->setParameter(self::EXTENSION_IDENTIFIER.'.debug.'.$name, $value);
110+
}
108111
}
109112

110113
/**
111114
* @param ContainerBuilder $container
112115
*/
113116
private function bindJsonRpcServerDispatcher(ContainerBuilder $container) : void
114117
{
115-
$dispatcherRef = new Reference('json_rpc_http_server.dispatcher.server');
118+
$dispatcherRef = new Reference(self::EXTENSION_IDENTIFIER.'.dispatcher.server');
116119
$dispatcherAwareServiceList = $container->findTaggedServiceIds(self::JSONRPC_SERVER_DISPATCHER_AWARE_TAG);
117120
foreach ($dispatcherAwareServiceList as $serviceId => $tagAttributeList) {
118121
$definition = $container->getDefinition($serviceId);
@@ -149,7 +152,7 @@ private function bindValidatorIfDefined(ContainerBuilder $container) : void
149152
/**
150153
* @param ContainerBuilder $container
151154
*/
152-
private function binJsonRpcMethods(ContainerBuilder $container) : void
155+
private function bindJsonRpcMethods(ContainerBuilder $container) : void
153156
{
154157
$mappingAwareServiceDefinitionList = $this->findAndValidateMappingAwareDefinitionList($container);
155158

@@ -166,7 +169,7 @@ private function binJsonRpcMethods(ContainerBuilder $container) : void
166169

167170
// Service locator for method resolver
168171
// => first argument is an array of wanted service with keys as alias for internal use
169-
$container->getDefinition('json_rpc_http_server.service_locator.method_resolver')
172+
$container->getDefinition(self::EXTENSION_IDENTIFIER.'.service_locator.method_resolver')
170173
->setArgument(0, $methodMappingList);
171174
}
172175

@@ -223,4 +226,12 @@ private function checkMethodAwareServiceIdList(
223226
));
224227
}
225228
}
229+
230+
private function bindDebug(ContainerBuilder $container) : void
231+
{
232+
if ($container->getParameter(self::EXTENSION_IDENTIFIER.'.debug.enabled')) {
233+
$container->getDefinition('json_rpc_server_sdk.app.serialization.jsonrpc_response_normalizer')
234+
->addArgument(new Reference('json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer'));
235+
}
236+
}
226237
}

src/JsonRpcHttpServerBundle.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use Symfony\Component\HttpKernel\Bundle\Bundle;
55

66
/**
7-
* Class JsonRpcHttpServerBundle
7+
* @see \Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension
88
*/
99
class JsonRpcHttpServerBundle extends Bundle
1010
{

src/Resources/config/sdk.services.app.yaml

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
services:
2-
#Serialization
2+
# Serialization
33
json_rpc_server_sdk.app.serialization.jsonrpc_request_denormalizer:
44
class: Yoanm\JsonRpcServer\App\Serialization\JsonRpcRequestDenormalizer
55

@@ -22,7 +22,7 @@ services:
2222
- '@json_rpc_server_sdk.app.serialization.jsonrpc_call_dernormalizer'
2323
- '@json_rpc_server_sdk.app.serialization.jsonrpc_call_response_normalizer'
2424

25-
#Handlers
25+
# Handlers
2626
json_rpc_server_sdk.app.handler.jsonrpc_request:
2727
class: Yoanm\JsonRpcServer\App\Handler\JsonRpcRequestHandler
2828
arguments:
@@ -39,3 +39,11 @@ services:
3939
# Creator
4040
json_rpc_server_sdk.app.creator.response:
4141
class: Yoanm\JsonRpcServer\App\Creator\ResponseCreator
42+
43+
# Debug
44+
json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer:
45+
class: Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseErrorNormalizer
46+
arguments:
47+
- '%json_rpc_http_server.debug.max_trace_size%'
48+
- '%json_rpc_http_server.debug.show_trace_arguments%'
49+
- '%json_rpc_http_server.debug.simplify_trace_arguments%'

tests/Functional/DependencyInjection/ConfigFilesTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Yoanm\JsonRpcServer\App\Serialization\JsonRpcCallSerializer;
1212
use Yoanm\JsonRpcServer\App\Serialization\JsonRpcRequestDenormalizer;
1313
use Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseNormalizer;
14+
use Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseErrorNormalizer;
1415
use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint;
1516
use Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension;
1617
use Yoanm\SymfonyJsonRpcHttpServer\Dispatcher\SymfonyJsonRpcServerDispatcher;
@@ -100,6 +101,11 @@ public function provideSDKAppServiceIdAndClass()
100101
'serviceClassName' => ResponseCreator::class,
101102
'public' => false,
102103
],
104+
'SDK - App - Response error normalizer' => [
105+
'serviceId' => 'json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer',
106+
'serviceClassName' => JsonRpcResponseErrorNormalizer::class,
107+
'public' => false,
108+
],
103109
];
104110
}
105111

tests/Functional/DependencyInjection/JsonRpcHttpServerExtensionTest.php

+18
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,22 @@ public function testShouldThowAnExceptionIfMethodAwareServiceDoesNotImplementRig
185185

186186
$this->loadContainer();
187187
}
188+
189+
public function testShouldAddDebugResponseErrorNormalizerIfDebugModeEnabled()
190+
{
191+
$this->loadContainer([
192+
'debug' => [
193+
'enabled' => true,
194+
]
195+
]);
196+
197+
// Assert response normalizer has responseErrorNormalizer as first argument
198+
$this->assertContainerBuilderHasServiceDefinitionWithArgument(
199+
'json_rpc_server_sdk.app.serialization.jsonrpc_response_normalizer',
200+
0,
201+
new Reference('json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer'),
202+
);
203+
204+
$this->assertEndpointIsUsable();
205+
}
188206
}

0 commit comments

Comments
 (0)