diff --git a/vendor/magento/module-graph-ql/Controller/GraphQl.php b/vendor/magento/module-graph-ql/Controller/GraphQl.php index f3536b9683d4e..853d42cf3f453 100644 --- a/vendor/magento/module-graph-ql/Controller/GraphQl.php +++ b/vendor/magento/module-graph-ql/Controller/GraphQl.php @@ -9,6 +9,8 @@ namespace Magento\GraphQl\Controller; +use Exception; +use GraphQL\Error\FormattedError; use GraphQL\Error\SyntaxError; use GraphQL\Language\Source; use Magento\Framework\App\Area; @@ -21,7 +23,10 @@ use Magento\Framework\App\ResponseInterface; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\GraphQl\Exception\ExceptionFormatter; +use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\InvalidRequestInterface; use Magento\Framework\GraphQl\Query\Fields as QueryFields; use Magento\Framework\GraphQl\Query\QueryParser; use Magento\Framework\GraphQl\Query\QueryProcessor; @@ -224,10 +229,8 @@ public function dispatch(RequestInterface $request): ResponseInterface $this->contextFactory->create(), $data['variables'] ?? [] ); - } catch (\Exception $error) { - $result['errors'] = isset($result['errors']) ? $result['errors'] : []; - $result['errors'][] = $this->graphQlError->create($error); - $statusCode = ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS; + } catch (Exception $error) { + [$result, $statusCode] = $this->handleGraphQlException($error); } $jsonResult->setHttpResponseCode($statusCode); @@ -243,6 +246,26 @@ public function dispatch(RequestInterface $request): ResponseInterface return $this->httpResponse; } + /** + * Handle GraphQL Exceptions + * + * @param Exception $e + * @return array + */ + private function handleGraphQlException(Exception $e): array + { + [$error, $statusCode] = match (true) { + $e instanceof InvalidRequestInterface => [FormattedError::createFromException($e), $e->getStatusCode()], + $e instanceof SyntaxError => [FormattedError::createFromException($e), 400], + $e instanceof GraphQlAuthenticationException => [$this->graphQlError->create($e), 401], + $e instanceof GraphQlAuthorizationException => [$this->graphQlError->create($e), 403], + $e instanceof GraphQlInputException => [FormattedError::createFromException($e), 200], + default => [$this->graphQlError->create($e), ExceptionFormatter::HTTP_GRAPH_QL_SCHEMA_ERROR_STATUS], + }; + + return [['errors' => [$error]], $statusCode]; + } + /** * Get data from request body or query string * @@ -267,10 +290,14 @@ private function getDataFromRequest(RequestInterface $request): array } } elseif ($request->isGet()) { $data = $request->getParams(); - $data['variables'] = isset($data['variables']) ? - $this->jsonSerializer->unserialize($data['variables']) : null; - $data['variables'] = is_array($data['variables']) ? - $data['variables'] : null; + try { + $data['variables'] = !empty($data['variables']) && is_string($data['variables']) + ? $this->jsonSerializer->unserialize($data['variables']) + : null; + } catch (\InvalidArgumentException) { + $source = new Source($data['variables']); + throw new SyntaxError($source, 0, 'Unable to parse the variables.'); + } } else { return []; } diff --git a/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/ContentTypeValidator.php b/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/ContentTypeValidator.php index 555048aac6771..a8e6a8478f4ce 100644 --- a/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/ContentTypeValidator.php +++ b/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/ContentTypeValidator.php @@ -1,14 +1,15 @@ isPost() && strpos($headerValue, $requiredHeaderValue) === false ) { - throw new GraphQlInputException( - new \Magento\Framework\Phrase('Request content type must be application/json') + throw new UnsupportedMediaTypeException( + new Phrase('Request content type must be application/json') ); } } diff --git a/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/HttpVerbValidator.php b/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/HttpVerbValidator.php index 56351c7711cec..ff4cb247175f9 100644 --- a/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/HttpVerbValidator.php +++ b/vendor/magento/module-graph-ql/Controller/HttpRequestValidator/HttpVerbValidator.php @@ -1,7 +1,7 @@ isSafe; + } +} diff --git a/vendor/magento/framework/GraphQl/Exception/UnsupportedMediaTypeException.php b/vendor/magento/framework/GraphQl/Exception/UnsupportedMediaTypeException.php new file mode 100644 index 0000000000000..6be650a3eb01b --- /dev/null +++ b/vendor/magento/framework/GraphQl/Exception/UnsupportedMediaTypeException.php @@ -0,0 +1,46 @@ +isSafe; + } +} diff --git a/vendor/magento/framework/GraphQl/Schema/SchemaGenerator.php b/vendor/magento/framework/GraphQl/Schema/SchemaGenerator.php index 250b80defa6dd..2a81b5d32ced2 100644 --- a/vendor/magento/framework/GraphQl/Schema/SchemaGenerator.php +++ b/vendor/magento/framework/GraphQl/Schema/SchemaGenerator.php @@ -1,13 +1,14 @@ $this->typeRegistry->get('Query'), 'mutation' => $this->typeRegistry->get('Mutation'), 'typeLoader' => function ($name) { - return $this->typeRegistry->get($name); + try { + return $this->typeRegistry->get($name); + } catch (GraphQlInputException) { + return null; + } }, 'types' => function () { $typesImplementors = []; diff --git a/vendor/magento/framework/GraphQl/Schema/Type/TypeRegistry.php b/vendor/magento/framework/GraphQl/Schema/Type/TypeRegistry.php index 414e1eebe6531..1b8cb47e4048d 100644 --- a/vendor/magento/framework/GraphQl/Schema/Type/TypeRegistry.php +++ b/vendor/magento/framework/GraphQl/Schema/Type/TypeRegistry.php @@ -1,12 +1,13 @@ types[$typeName])) { - $configElement = $this->config->getConfigElement($typeName); + try { + $configElement = $this->config->getConfigElement($typeName); + } catch (LogicException) { + throw new GraphQlInputException( + new Phrase('Unknown type "%1".', [$typeName]) + ); + } $configElementClass = get_class($configElement); if (!isset($this->configToTypeMap[$configElementClass])) {