From 72780834361cba061e1aafbaecc9e8112110bdd9 Mon Sep 17 00:00:00 2001 From: yoanm Date: Sun, 30 Apr 2023 15:51:20 +0200 Subject: [PATCH 1/2] Misc: improve (#94) - ignore useless files for archives - ignore phpcs warning on scrutinizer - improve abstract kernel --- .gitattributes | 4 ++++ .scrutinizer.yml | 1 + features/demo_app/src/AbstractKernel.php | 8 ++++++-- features/demo_app/src/DefaultKernel.php | 5 ----- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index 67ae023..500a7cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,6 +4,10 @@ /.gitignore export-ignore /.scrutinizer.yml export-ignore /.travis.yml export-ignore +/.editorconfig export-ignore +/codecov.yml export-ignore +/.remarkrc export-ignore +/.remarkignore export-ignore /behat.yml export-ignore /phpunit.xml.dist export-ignore /phpcs.xml.dist export-ignore diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 5e6d01b..b579dd2 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -44,6 +44,7 @@ build: COMPOSER_OPTIONS: '--optimize-autoloader' COVERAGE_OUTPUT_STYLE: 'clover' COVERAGE_CLOVER_FILE_PATH: 'build/coverage/clover.xml' + PHPCS_DISABLE_WARNING: 'true' php: version: "8.2" ini: diff --git a/features/demo_app/src/AbstractKernel.php b/features/demo_app/src/AbstractKernel.php index 62897dc..d874983 100644 --- a/features/demo_app/src/AbstractKernel.php +++ b/features/demo_app/src/AbstractKernel.php @@ -57,6 +57,11 @@ public function getProjectDir(): string return realpath(__DIR__.'/../'); } + public function getConfigDir(): string + { + return $this->getProjectDir().'/'.$this->getConfigDirectoryName(); + } + /** * @param RouteCollectionBuilder|RoutingConfigurator $routes */ @@ -69,7 +74,7 @@ protected function configureRoutes($routes) $routes->import($confDir . '/routes' . self::CONFIG_EXTS, '/', 'glob'); } } - + /** * {@inheritdoc} */ @@ -93,5 +98,4 @@ protected function getContainerClass(): string } abstract public function getConfigDirectoryName() : string; - abstract public function getConfigDir(): string; } diff --git a/features/demo_app/src/DefaultKernel.php b/features/demo_app/src/DefaultKernel.php index de495b7..f91f2d0 100644 --- a/features/demo_app/src/DefaultKernel.php +++ b/features/demo_app/src/DefaultKernel.php @@ -10,9 +10,4 @@ public function getConfigDirectoryName() : string { return 'default_config'; } - - public function getConfigDir(): string - { - return $this->getProjectDir().'/'.$this->getConfigDirectoryName(); - } } From 864226d4ef7e4225883941277f1ca1a6aa8f563d Mon Sep 17 00:00:00 2001 From: Paul Klimov Date: Sun, 30 Apr 2023 17:23:31 +0300 Subject: [PATCH 2/2] Add configurable debug mode (#93) --- README.md | 30 +++++++++++++++++++ composer.json | 2 +- src/DependencyInjection/Configuration.php | 24 +++++++++++++++ .../JsonRpcHttpServerExtension.php | 25 +++++++++++----- src/JsonRpcHttpServerBundle.php | 2 +- src/Resources/config/sdk.services.app.yaml | 12 ++++++-- .../DependencyInjection/ConfigFilesTest.php | 6 ++++ .../JsonRpcHttpServerExtensionTest.php | 18 +++++++++++ 8 files changed, 108 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 6c61d13..e969118 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,36 @@ mapping_aware_service: tags: ['json_rpc_http_server.method_aware'] ``` +## Debug mode + +You can setup 'debug' mode for the JSON-RPC server, which allows display of verbose error information within the response JSON body. +This information contains actual exception class name, code, message and stack trace. + +> Note: you should never enable 'debug' mode in 'production' environment, since it will expose vital internal information to the API consumer. + +Configuration example: + +```yaml +# file 'config/packages/json_rpc.yaml' +json_rpc_http_server: + endpoint: '/json-rpc' + debug: + enabled: false + max_trace_size: 10 + show_trace_arguments: true + simplify_trace_arguments: true + +when@dev: + json_rpc_http_server: + debug: + enabled: true + +when@test: + json_rpc_http_server: + debug: + enabled: true +``` + ## Contributing See [contributing note](./CONTRIBUTING.md) diff --git a/composer.json b/composer.json index cf17ee9..d604774 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "symfony/event-dispatcher-contracts": "^1.0 || ^2.0 || ^3.0", "symfony/http-foundation": "^4.4 || ^5.4 || ^6.0", "symfony/http-kernel": "^4.4 || ^5.4 || ^6.0", - "yoanm/jsonrpc-server-sdk": "^3.0" + "yoanm/jsonrpc-server-sdk": "^3.3" }, "require-dev": { "behat/behat": "^3.9.0", diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 0f7e9e2..5bf6c1a 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -22,6 +22,30 @@ public function getConfigTreeBuilder() ->treatNullLike(self::DEFAULT_ENDPOINT) ->defaultValue(self::DEFAULT_ENDPOINT) ->end() + ->arrayNode('debug') + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('enabled') + ->info( + 'Whether to render debug information on error or not (should NOT be enabled on prod)' + ) + ->defaultFalse() + ->end() + ->integerNode('max_trace_size') + ->info('Max debug trace size') + ->min(0) + ->defaultValue(10) + ->end() + ->booleanNode('show_trace_arguments') + ->info('Whether to render debug stack trace arguments or not') + ->defaultValue(true) + ->end() + ->booleanNode('simplify_trace_arguments') + ->info('Whether to simplify representation of debug stack trace arguments or not') + ->defaultValue(true) + ->end() + ->end() + ->end() ->end() ; diff --git a/src/DependencyInjection/JsonRpcHttpServerExtension.php b/src/DependencyInjection/JsonRpcHttpServerExtension.php index 9922002..d793025 100644 --- a/src/DependencyInjection/JsonRpcHttpServerExtension.php +++ b/src/DependencyInjection/JsonRpcHttpServerExtension.php @@ -14,7 +14,7 @@ use Yoanm\JsonRpcServer\Domain\JsonRpcMethodAwareInterface; /** - * Class JsonRpcHttpServerExtension + * @see \Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\Configuration */ class JsonRpcHttpServerExtension implements ExtensionInterface, CompilerPassInterface { @@ -66,7 +66,8 @@ public function process(ContainerBuilder $container) { $this->bindJsonRpcServerDispatcher($container); $this->bindValidatorIfDefined($container); - $this->binJsonRpcMethods($container); + $this->bindJsonRpcMethods($container); + $this->bindDebug($container); } /** @@ -102,9 +103,11 @@ private function compileAndProcessConfigurations(array $configs, ContainerBuilde $configuration = new Configuration(); $config = (new Processor())->processConfiguration($configuration, $configs); - $httpEndpointPath = $config['endpoint']; + $container->setParameter(self::ENDPOINT_PATH_CONTAINER_PARAM_ID, $config['endpoint']); - $container->setParameter(self::ENDPOINT_PATH_CONTAINER_PARAM_ID, $httpEndpointPath); + foreach ($config['debug'] as $name => $value) { + $container->setParameter(self::EXTENSION_IDENTIFIER.'.debug.'.$name, $value); + } } /** @@ -112,7 +115,7 @@ private function compileAndProcessConfigurations(array $configs, ContainerBuilde */ private function bindJsonRpcServerDispatcher(ContainerBuilder $container) : void { - $dispatcherRef = new Reference('json_rpc_http_server.dispatcher.server'); + $dispatcherRef = new Reference(self::EXTENSION_IDENTIFIER.'.dispatcher.server'); $dispatcherAwareServiceList = $container->findTaggedServiceIds(self::JSONRPC_SERVER_DISPATCHER_AWARE_TAG); foreach ($dispatcherAwareServiceList as $serviceId => $tagAttributeList) { $definition = $container->getDefinition($serviceId); @@ -149,7 +152,7 @@ private function bindValidatorIfDefined(ContainerBuilder $container) : void /** * @param ContainerBuilder $container */ - private function binJsonRpcMethods(ContainerBuilder $container) : void + private function bindJsonRpcMethods(ContainerBuilder $container) : void { $mappingAwareServiceDefinitionList = $this->findAndValidateMappingAwareDefinitionList($container); @@ -166,7 +169,7 @@ private function binJsonRpcMethods(ContainerBuilder $container) : void // Service locator for method resolver // => first argument is an array of wanted service with keys as alias for internal use - $container->getDefinition('json_rpc_http_server.service_locator.method_resolver') + $container->getDefinition(self::EXTENSION_IDENTIFIER.'.service_locator.method_resolver') ->setArgument(0, $methodMappingList); } @@ -223,4 +226,12 @@ private function checkMethodAwareServiceIdList( )); } } + + private function bindDebug(ContainerBuilder $container) : void + { + if ($container->getParameter(self::EXTENSION_IDENTIFIER.'.debug.enabled')) { + $container->getDefinition('json_rpc_server_sdk.app.serialization.jsonrpc_response_normalizer') + ->addArgument(new Reference('json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer')); + } + } } diff --git a/src/JsonRpcHttpServerBundle.php b/src/JsonRpcHttpServerBundle.php index 2a25db6..20c6bae 100644 --- a/src/JsonRpcHttpServerBundle.php +++ b/src/JsonRpcHttpServerBundle.php @@ -4,7 +4,7 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; /** - * Class JsonRpcHttpServerBundle + * @see \Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension */ class JsonRpcHttpServerBundle extends Bundle { diff --git a/src/Resources/config/sdk.services.app.yaml b/src/Resources/config/sdk.services.app.yaml index f49b866..09c0f1f 100644 --- a/src/Resources/config/sdk.services.app.yaml +++ b/src/Resources/config/sdk.services.app.yaml @@ -1,5 +1,5 @@ services: - #Serialization + # Serialization json_rpc_server_sdk.app.serialization.jsonrpc_request_denormalizer: class: Yoanm\JsonRpcServer\App\Serialization\JsonRpcRequestDenormalizer @@ -22,7 +22,7 @@ services: - '@json_rpc_server_sdk.app.serialization.jsonrpc_call_dernormalizer' - '@json_rpc_server_sdk.app.serialization.jsonrpc_call_response_normalizer' - #Handlers + # Handlers json_rpc_server_sdk.app.handler.jsonrpc_request: class: Yoanm\JsonRpcServer\App\Handler\JsonRpcRequestHandler arguments: @@ -39,3 +39,11 @@ services: # Creator json_rpc_server_sdk.app.creator.response: class: Yoanm\JsonRpcServer\App\Creator\ResponseCreator + + # Debug + json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer: + class: Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseErrorNormalizer + arguments: + - '%json_rpc_http_server.debug.max_trace_size%' + - '%json_rpc_http_server.debug.show_trace_arguments%' + - '%json_rpc_http_server.debug.simplify_trace_arguments%' diff --git a/tests/Functional/DependencyInjection/ConfigFilesTest.php b/tests/Functional/DependencyInjection/ConfigFilesTest.php index 0f982f9..2b8e846 100644 --- a/tests/Functional/DependencyInjection/ConfigFilesTest.php +++ b/tests/Functional/DependencyInjection/ConfigFilesTest.php @@ -11,6 +11,7 @@ use Yoanm\JsonRpcServer\App\Serialization\JsonRpcCallSerializer; use Yoanm\JsonRpcServer\App\Serialization\JsonRpcRequestDenormalizer; use Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseNormalizer; +use Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseErrorNormalizer; use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint; use Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection\JsonRpcHttpServerExtension; use Yoanm\SymfonyJsonRpcHttpServer\Dispatcher\SymfonyJsonRpcServerDispatcher; @@ -100,6 +101,11 @@ public function provideSDKAppServiceIdAndClass() 'serviceClassName' => ResponseCreator::class, 'public' => false, ], + 'SDK - App - Response error normalizer' => [ + 'serviceId' => 'json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer', + 'serviceClassName' => JsonRpcResponseErrorNormalizer::class, + 'public' => false, + ], ]; } diff --git a/tests/Functional/DependencyInjection/JsonRpcHttpServerExtensionTest.php b/tests/Functional/DependencyInjection/JsonRpcHttpServerExtensionTest.php index 2aac4c7..7ab86df 100644 --- a/tests/Functional/DependencyInjection/JsonRpcHttpServerExtensionTest.php +++ b/tests/Functional/DependencyInjection/JsonRpcHttpServerExtensionTest.php @@ -185,4 +185,22 @@ public function testShouldThowAnExceptionIfMethodAwareServiceDoesNotImplementRig $this->loadContainer(); } + + public function testShouldAddDebugResponseErrorNormalizerIfDebugModeEnabled() + { + $this->loadContainer([ + 'debug' => [ + 'enabled' => true, + ] + ]); + + // Assert response normalizer has responseErrorNormalizer as first argument + $this->assertContainerBuilderHasServiceDefinitionWithArgument( + 'json_rpc_server_sdk.app.serialization.jsonrpc_response_normalizer', + 0, + new Reference('json_rpc_server_sdk.app.serialization.jsonrpc_response_error_normalizer'), + ); + + $this->assertEndpointIsUsable(); + } }