drupal-graphql / drupal-graphql/graphql
Some invalid queries may return a 500 Internal Server Error
- Dominant language
- PHP
- Stars
- 287
- Forks
- 198
- PR merge metrics
- No merged PRs in 30d
Description
Disclaimer: I'm not that experienced in the domain of GraphQL, so I may very well have the wrong expectations here.
It is my understanding that (when using GraphQL over HTTP), the HTTP response status code is always 200 for queries that generate an error. For example, the Drupal GraphQL module correctly returns a 200 HTTP response status code for the following invalid query:
```
{
"errors": [
{
"message": "Cannot query field \"unknownField\" on type \"NodeArticle\".",
"category": "graphql",
"locations": [
{
"line": 5,
"column": 9
}
]
}
]
}
```
However, the following query results in a 500 Internal Server Error:
```
{
nodeQuery {
entities {
... on NodeBundleThatDoesNotExist {
unknownField
}
}
}
}
```
```
The website encountered an unexpected error. Please try again later.
LogicException: Missing type NodeBundleThatDoesNotExist. in Drupal\graphql\Plugin\GraphQL\Schemas\SchemaPluginBase->getType() (line 421 of modules/contrib/graphql/src/Plugin/GraphQL/Schemas/SchemaPluginBase.php).
Drupal\graphql\Plugin\GraphQL\Schemas\SchemaPluginBase->Drupal\graphql\Plugin\GraphQL\Schemas\{closure}('NodeBundleThatDoesNotExist') (Line: 319)
GraphQL\Type\Schema->loadType('NodeBundleThatDoesNotExist') (Line: 212)
GraphQL\Type\Schema->getType('NodeBundleThatDoesNotExist') (Line: 504)
GraphQL\Utils\AST::typeFromAST(Object, Object) (Line: 66)
GraphQL\Utils\TypeInfo::typeFromAST(Object, Object) (Line: 825)
GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged->internalCollectFieldsAndFragmentNames(Object, Object, Object, Array, Array) (Line: 739)
GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged->getFieldsAndFragmentNames(Object, Object, Object) (Line: 162)
GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged->findConflictsWithinSelectionSet(Object, Object, Object) (Line: 71)
GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged->GraphQL\Validator\Rules\{closure}(Object, 'selectionSet', Object, Array, Array)
call_user_func_array(Object, Array) (Line: 372)
GraphQL\Language\Visitor::GraphQL\Language\{closure}(Object, 'selectionSet', Object, Array, Array)
call_user_func_array(Object, Array) (Line: 426)
GraphQL\Language\Visitor::GraphQL\Language\{closure}(Object, 'selectionSet', Object, Array, Array)
call_user_func(Object, Object, 'selectionSet', Object, Array, Array) (Line: 251)
GraphQL\Language\Visitor::visit(Object, Array) (Line: 365)
Drupal\graphql\GraphQL\Execution\QueryProcessor->validateOperation(Object, Object, Object) (Line: 287)
Drupal\graphql\GraphQL\Execution\QueryProcessor->doExecuteOperation(Object, Object, Object, Object, 1) (Line: 241)
Drupal\graphql\GraphQL\Execution\QueryProcessor->executeCacheableOperation(Object, Object, Object, Object, 1) (Line: 204)
Drupal\graphql\GraphQL\Execution\QueryProcessor->executeOperation(Object, Object, Object, ) (Line: 149)
Drupal\graphql\GraphQL\Execution\QueryProcessor->executeOperationWithReporting(Object, Object, Object, ) (Line: 120)
Drupal\graphql\GraphQL\Execution\QueryProcessor->executeSingle(Object, Object) (Line: 109)
Drupal\graphql\GraphQL\Execution\QueryProcessor->processQuery('default:default', Object) (Line: 59)
Drupal\graphql\Controller\RequestController->handleSingle('default:default', Object) (Line: 70)
Drupal\graphql\Controller\RequestController->handleRequest('default:default', Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 573)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 151)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
```
I'm wondering if this is works as designed or this could be improved upon?
Catching all exceptions (`\Exception`) @ https://github.com/drupal-graphql/graphql/blob/8.x-3.x/src/GraphQL/Execution/QueryProcessor.php#L219 would solve this. The query above would then generate the following response (with 200 HTTP status code):
```
{
"errors": [
{
"message": "Internal server error",
"category": "internal"
}
]
}
```
But I'm unsure if this can cause any unintended consequences?
PS: the examples above are based on the 3.x version of the module. I haven't tested this on the 4.x version yet.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.