mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-21 20:36:05 +03:00
Add Debug::RETHROW_UNSAFE_EXCEPTIONS flag
This allows for a more granular default for which Exceptions are thrown, taking the settings made through the ClientAware interface into account. - Add docs - Add a test case - Differentiate clearly from other test
This commit is contained in:
parent
503ac4619a
commit
326e0b4719
@ -84,7 +84,7 @@ To change default **"Internal server error"** message to something else, use:
|
||||
GraphQL\Error\FormattedError::setInternalErrorMessage("Unexpected error");
|
||||
```
|
||||
|
||||
#Debugging tools
|
||||
# Debugging tools
|
||||
|
||||
During development or debugging use `$result->toArray(true)` to add **debugMessage** key to
|
||||
each formatted error entry. If you also want to add exception trace - pass flags instead:
|
||||
@ -116,7 +116,7 @@ This will make each error entry to look like this:
|
||||
];
|
||||
```
|
||||
|
||||
If you prefer first resolver exception to be re-thrown, use following flags:
|
||||
If you prefer the first resolver exception to be re-thrown, use following flags:
|
||||
```php
|
||||
<?php
|
||||
use GraphQL\GraphQL;
|
||||
@ -127,6 +127,9 @@ $debug = Debug::INCLUDE_DEBUG_MESSAGE | Debug::RETHROW_INTERNAL_EXCEPTIONS;
|
||||
$result = GraphQL::executeQuery(/*args*/)->toArray($debug);
|
||||
```
|
||||
|
||||
If you only want to re-throw Exceptions that are not marked as safe through the `ClientAware` interface, use
|
||||
the flag `Debug::RETHROW_UNSAFE_EXCEPTIONS`.
|
||||
|
||||
# Custom Error Handling and Formatting
|
||||
It is possible to define custom **formatter** and **handler** for result errors.
|
||||
|
||||
|
@ -12,4 +12,5 @@ class Debug
|
||||
const INCLUDE_DEBUG_MESSAGE = 1;
|
||||
const INCLUDE_TRACE = 2;
|
||||
const RETHROW_INTERNAL_EXCEPTIONS = 4;
|
||||
const RETHROW_UNSAFE_EXCEPTIONS = 8;
|
||||
}
|
||||
|
@ -235,9 +235,7 @@ class FormattedError
|
||||
|
||||
$debug = (int) $debug;
|
||||
|
||||
$isInternal = ! $e instanceof ClientAware || ! $e->isClientSafe();
|
||||
|
||||
if (($debug & Debug::RETHROW_INTERNAL_EXCEPTIONS) && $isInternal) {
|
||||
if ($debug & Debug::RETHROW_INTERNAL_EXCEPTIONS) {
|
||||
if (! $e instanceof Error) {
|
||||
throw $e;
|
||||
}
|
||||
@ -247,7 +245,15 @@ class FormattedError
|
||||
}
|
||||
}
|
||||
|
||||
if (($debug & Debug::INCLUDE_DEBUG_MESSAGE) && $isInternal) {
|
||||
$isUnsafe = ! $e instanceof ClientAware || ! $e->isClientSafe();
|
||||
|
||||
if(($debug & Debug::RETHROW_UNSAFE_EXCEPTIONS) && $isUnsafe){
|
||||
if ($e->getPrevious()) {
|
||||
throw $e->getPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
if (($debug & Debug::INCLUDE_DEBUG_MESSAGE) && $isUnsafe) {
|
||||
// Displaying debugMessage as a first entry:
|
||||
$formattedError = ['debugMessage' => $e->getMessage()] + $formattedError;
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
<?php
|
||||
namespace GraphQL\Tests\Server;
|
||||
|
||||
use GraphQL\Deferred;
|
||||
use GraphQL\Error\Debug;
|
||||
use GraphQL\Error\Error;
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Error\UserError;
|
||||
use GraphQL\Executor\ExecutionResult;
|
||||
use GraphQL\Language\AST\DocumentNode;
|
||||
use GraphQL\Language\Parser;
|
||||
@ -64,20 +62,20 @@ class QueryExecutionTest extends ServerTestCase
|
||||
|
||||
$query = '
|
||||
{
|
||||
fieldWithException
|
||||
fieldWithSafeException
|
||||
f1
|
||||
}
|
||||
';
|
||||
|
||||
$expected = [
|
||||
'data' => [
|
||||
'fieldWithException' => null,
|
||||
'fieldWithSafeException' => null,
|
||||
'f1' => 'f1'
|
||||
],
|
||||
'errors' => [
|
||||
[
|
||||
'message' => 'This is the exception we want',
|
||||
'path' => ['fieldWithException'],
|
||||
'path' => ['fieldWithSafeException'],
|
||||
'trace' => []
|
||||
]
|
||||
]
|
||||
@ -86,6 +84,18 @@ class QueryExecutionTest extends ServerTestCase
|
||||
$result = $this->executeQuery($query)->toArray();
|
||||
$this->assertArraySubset($expected, $result);
|
||||
}
|
||||
|
||||
public function testRethrowUnsafeExceptions() : void
|
||||
{
|
||||
$this->config->setDebug(Debug::RETHROW_UNSAFE_EXCEPTIONS);
|
||||
$this->expectException(UnsafeException::class);
|
||||
|
||||
$this->executeQuery('
|
||||
{
|
||||
fieldWithUnsafeException
|
||||
}
|
||||
')->toArray();
|
||||
}
|
||||
|
||||
public function testPassesRootValueAndContext() : void
|
||||
{
|
||||
@ -240,7 +250,7 @@ class QueryExecutionTest extends ServerTestCase
|
||||
'query' => '{invalid}'
|
||||
],
|
||||
[
|
||||
'query' => '{f1,fieldWithException}'
|
||||
'query' => '{f1,fieldWithSafeException}'
|
||||
]
|
||||
];
|
||||
|
||||
@ -405,7 +415,7 @@ class QueryExecutionTest extends ServerTestCase
|
||||
'query' => '{invalid}'
|
||||
],
|
||||
[
|
||||
'query' => '{f1,fieldWithException}'
|
||||
'query' => '{f1,fieldWithSafeException}'
|
||||
],
|
||||
[
|
||||
'query' => '
|
||||
@ -427,7 +437,7 @@ class QueryExecutionTest extends ServerTestCase
|
||||
[
|
||||
'data' => [
|
||||
'f1' => 'f1',
|
||||
'fieldWithException' => null
|
||||
'fieldWithSafeException' => null
|
||||
],
|
||||
'errors' => [
|
||||
['message' => 'This is the exception we want']
|
||||
@ -581,7 +591,7 @@ class QueryExecutionTest extends ServerTestCase
|
||||
return ['test' => 'formatted'];
|
||||
});
|
||||
|
||||
$result = $this->executeQuery('{fieldWithException}');
|
||||
$result = $this->executeQuery('{fieldWithSafeException}');
|
||||
$this->assertFalse($called);
|
||||
$formatted = $result->toArray();
|
||||
$expected = [
|
||||
@ -620,7 +630,7 @@ class QueryExecutionTest extends ServerTestCase
|
||||
];
|
||||
});
|
||||
|
||||
$result = $this->executeQuery('{fieldWithException,test: fieldWithException}');
|
||||
$result = $this->executeQuery('{fieldWithSafeException,test: fieldWithSafeException}');
|
||||
|
||||
$this->assertFalse($called);
|
||||
$formatted = $result->toArray();
|
||||
|
@ -3,6 +3,7 @@ namespace GraphQL\Tests\Server;
|
||||
|
||||
|
||||
use GraphQL\Deferred;
|
||||
use GraphQL\Error\ClientAware;
|
||||
use GraphQL\Error\UserError;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
@ -34,10 +35,16 @@ abstract class ServerTestCase extends TestCase
|
||||
return $info->fieldName;
|
||||
}
|
||||
],
|
||||
'fieldWithException' => [
|
||||
'fieldWithSafeException' => [
|
||||
'type' => Type::string(),
|
||||
'resolve' => function($root, $args, $context, $info) {
|
||||
throw new UserError("This is the exception we want");
|
||||
'resolve' => function() {
|
||||
throw new UserError('This is the exception we want');
|
||||
}
|
||||
],
|
||||
'fieldWithUnsafeException' => [
|
||||
'type' => Type::string(),
|
||||
'resolve' => function() {
|
||||
throw new UnsafeException('This exception should not be shown to the user');
|
||||
}
|
||||
],
|
||||
'testContextAndRootValue' => [
|
||||
@ -92,3 +99,30 @@ abstract class ServerTestCase extends TestCase
|
||||
return $schema;
|
||||
}
|
||||
}
|
||||
|
||||
class UnsafeException extends \Exception implements ClientAware
|
||||
{
|
||||
/**
|
||||
* Returns true when exception message is safe to be displayed to a client.
|
||||
*
|
||||
* @api
|
||||
* @return bool
|
||||
*/
|
||||
public function isClientSafe()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string describing a category of the error.
|
||||
*
|
||||
* Value "graphql" is reserved for errors produced by query parsing or validation, do not use it.
|
||||
*
|
||||
* @api
|
||||
* @return string
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
return 'unsafe';
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user