-
Notifications
You must be signed in to change notification settings - Fork 3
#81: add JsonRpcResponseNormalizer::$debug
#82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
5dde428
#81: add `JsonRpcResponseNormalizer::$debug` allowing rendering error…
klimov-paul 44f953e
#81: extract `JsonRpcResponseErrorNormalizer` for error debug renderi…
klimov-paul 2bfe8aa
#81: improve condition for trace arguments presence
klimov-paul 8693b14
Merge branch 'master' of github.com:yoanm/php-jsonrpc-server-sdk into…
yoanm 2945580
Merge branch 'master' into 81-internal-server-error
yoanm bd3a709
Fix FTs
yoanm 118d0ab
Add FT with debug mode enabled
yoanm 5ad2980
Lint
yoanm 67a42b3
Cover all argument types conversion
yoanm 1b01952
Decrease method complexity
yoanm 03dd688
Merge branch 'master' into 81-internal-server-error
yoanm 728ed2a
#81: remove redundant condition
klimov-paul c775a5e
#81: fix debug assoc array simple rendering
klimov-paul a9029df
Merge branch 'master' into 81-internal-server-error
yoanm f5cc760
Improve coverage
yoanm c1986e4
Update README
yoanm 20b4111
Force arguments availability on stack trace
yoanm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
src/App/Serialization/JsonRpcResponseErrorNormalizer.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?php | ||
namespace Yoanm\JsonRpcServer\App\Serialization; | ||
|
||
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcExceptionInterface; | ||
|
||
/** | ||
* JsonRpcResponseErrorNormalizer prepares response data for the "unexpected" errors occur during request processing. | ||
* | ||
* It handles "internal server error" appearance in the response. | ||
* Instance of this class should be attached to {@see \Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseNormalizer} only in "debug" mode, | ||
* since it will expose vital internal information to the API consumer. | ||
* | ||
* @see \Yoanm\JsonRpcServer\App\Serialization\JsonRpcResponseNormalizer::normalizeError() | ||
*/ | ||
class JsonRpcResponseErrorNormalizer | ||
{ | ||
/** | ||
* @var int maximum count of trace lines to be displayed. | ||
*/ | ||
private $maxTraceSize; | ||
|
||
/** | ||
* @var bool whether to show trace arguments. | ||
*/ | ||
private $showTraceArguments; | ||
|
||
/** | ||
* @var bool whether to simplify trace arguments representation. | ||
*/ | ||
private $simplifyTraceArguments; | ||
|
||
/** | ||
* @param int $maxTraceSize maximum count of trace lines to be displayed. | ||
* @param bool $showTraceArguments whether to show trace arguments. | ||
* @param bool $simplifyTraceArguments whether to simplify trace arguments representation. | ||
*/ | ||
public function __construct(int $maxTraceSize = 10, bool $showTraceArguments = true, bool $simplifyTraceArguments = true) | ||
{ | ||
$this->maxTraceSize = $maxTraceSize; | ||
$this->showTraceArguments = $showTraceArguments; | ||
$this->simplifyTraceArguments = $simplifyTraceArguments; | ||
} | ||
|
||
/** | ||
* @param JsonRpcExceptionInterface $error | ||
* @return array | ||
*/ | ||
public function normalize(JsonRpcExceptionInterface $error) : array | ||
{ | ||
// `JsonRpcExceptionInterface` has a little value regarding debug error data composition on its own, | ||
// thus use previous exception, if available: | ||
return $this->composeDebugErrorData($error->getPrevious() ?? $error); | ||
} | ||
|
||
/** | ||
* @param \Throwable $error | ||
* @return array | ||
*/ | ||
private function composeDebugErrorData(\Throwable $error) : array | ||
{ | ||
$data = [ | ||
'_class' => get_class($error), | ||
'_code' => $error->getCode(), | ||
'_message' => $error->getMessage(), | ||
]; | ||
|
||
$trace = $this->filterErrorTrace($error->getTrace()); | ||
if (!empty($trace)) { | ||
$data['_trace'] = $trace; | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
/** | ||
* @param array $trace raw exception stack trace. | ||
* @return array simplified stack trace. | ||
*/ | ||
private function filterErrorTrace(array $trace): array | ||
{ | ||
$trace = array_slice($trace, 0, $this->maxTraceSize); | ||
|
||
$result = []; | ||
foreach ($trace as $entry) { | ||
if (array_key_exists('args', $entry)) { | ||
if ($this->showTraceArguments) { | ||
if ($this->simplifyTraceArguments) { | ||
$entry['args'] = $this->simplifyArguments($entry['args']); | ||
} | ||
} else { | ||
unset($entry['args']); | ||
} | ||
} | ||
|
||
$result[] = $entry; | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* Converts arguments array to their simplified representation. | ||
* | ||
* @param array $args arguments array to be converted. | ||
* @return string string representation of the arguments array. | ||
*/ | ||
private function simplifyArguments(array $args) : string | ||
{ | ||
$count = 0; | ||
|
||
$isAssoc = $args !== array_values($args); | ||
|
||
foreach ($args as $key => $value) { | ||
$count++; | ||
|
||
if ($count >= 5) { | ||
if ($count > 5) { | ||
unset($args[$key]); | ||
} else { | ||
$args[$key] = '...'; | ||
} | ||
|
||
continue; | ||
} | ||
|
||
$args[$key] = $this->simplifyArgument($value); | ||
|
||
if (is_string($key)) { | ||
$args[$key] = "'" . $key . "' => " . $args[$key]; | ||
} elseif ($isAssoc) { | ||
yoanm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// contains both numeric and string keys: | ||
$args[$key] = $key.' => '.$args[$key]; | ||
} | ||
} | ||
|
||
return implode(', ', $args); | ||
} | ||
|
||
private function simplifyArgument(mixed $value): mixed | ||
{ | ||
if (is_object($value)) { | ||
return get_class($value); | ||
} elseif (is_bool($value)) { | ||
return $value ? 'true' : 'false'; | ||
} elseif (is_string($value)) { | ||
if (strlen($value) > 64) { | ||
return "'" . substr($value, 0, 64) . "...'"; | ||
} else { | ||
return "'" . $value . "'"; | ||
} | ||
} elseif (is_array($value)) { | ||
return '[' . $this->simplifyArguments($value) . ']'; | ||
} elseif ($value === null) { | ||
return 'null'; | ||
} elseif (is_resource($value)) { | ||
return 'resource'; | ||
} | ||
|
||
return $value; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.