mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-26 14:56:03 +03:00
Server: ability to execute PSR7 request
This commit is contained in:
parent
87c812b221
commit
b2ec265d4f
@ -14,6 +14,7 @@ use GraphQL\Language\Parser;
|
|||||||
use GraphQL\Utils\AST;
|
use GraphQL\Utils\AST;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
use GraphQL\Validator\DocumentValidator;
|
use GraphQL\Validator\DocumentValidator;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Helper
|
* Class Helper
|
||||||
@ -146,12 +147,8 @@ class Helper
|
|||||||
* @throws Error
|
* @throws Error
|
||||||
* @throws InvariantViolation
|
* @throws InvariantViolation
|
||||||
*/
|
*/
|
||||||
public function loadPersistedQuery(ServerConfig $config, OperationParams $op)
|
private function loadPersistedQuery(ServerConfig $config, OperationParams $op)
|
||||||
{
|
{
|
||||||
if (!$op->queryId) {
|
|
||||||
throw new InvariantViolation("Could not load persisted query: queryId is not set");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load query if we got persisted query id:
|
// Load query if we got persisted query id:
|
||||||
$loader = $config->getPersistentQueryLoader();
|
$loader = $config->getPersistentQueryLoader();
|
||||||
|
|
||||||
@ -177,7 +174,7 @@ class Helper
|
|||||||
* @param OperationParams $params
|
* @param OperationParams $params
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function resolveValidationRules(ServerConfig $config, OperationParams $params)
|
private function resolveValidationRules(ServerConfig $config, OperationParams $params)
|
||||||
{
|
{
|
||||||
// Allow customizing validation rules per operation:
|
// Allow customizing validation rules per operation:
|
||||||
$validationRules = $config->getValidationRules();
|
$validationRules = $config->getValidationRules();
|
||||||
@ -197,8 +194,8 @@ class Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses HTTP request and returns GraphQL QueryParams contained in this request.
|
* Parses HTTP request and returns GraphQL OperationParams contained in this request.
|
||||||
* For batched requests it returns an array of QueryParams.
|
* For batched requests it returns an array of OperationParams.
|
||||||
*
|
*
|
||||||
* This function doesn't check validity of these params.
|
* This function doesn't check validity of these params.
|
||||||
*
|
*
|
||||||
@ -211,44 +208,88 @@ class Helper
|
|||||||
public function parseHttpRequest(callable $readRawBodyFn = null)
|
public function parseHttpRequest(callable $readRawBodyFn = null)
|
||||||
{
|
{
|
||||||
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null;
|
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null;
|
||||||
|
$bodyParams = [];
|
||||||
|
$urlParams = $_GET;
|
||||||
|
|
||||||
if ($method === 'GET') {
|
if ($method === 'POST') {
|
||||||
$result = OperationParams::create($_GET, true);
|
|
||||||
} else if ($method === 'POST') {
|
|
||||||
$contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : null;
|
$contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : null;
|
||||||
|
|
||||||
if (stripos($contentType, 'application/graphql') !== false) {
|
if (stripos($contentType, 'application/graphql') !== false) {
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
||||||
$result = OperationParams::create(['query' => $rawBody ?: '']);
|
$bodyParams = ['query' => $rawBody ?: ''];
|
||||||
} else if (stripos($contentType, 'application/json') !== false) {
|
} else if (stripos($contentType, 'application/json') !== false) {
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
||||||
$body = json_decode($rawBody ?: '', true);
|
$bodyParams = json_decode($rawBody ?: '', true);
|
||||||
|
|
||||||
if (json_last_error()) {
|
if (json_last_error()) {
|
||||||
throw new Error("Could not parse JSON: " . json_last_error_msg());
|
throw new Error("Could not parse JSON: " . json_last_error_msg());
|
||||||
}
|
}
|
||||||
if (!is_array($body)) {
|
if (!is_array($bodyParams)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"GraphQL Server expects JSON object or array, but got " .
|
"GraphQL Server expects JSON object or array, but got " .
|
||||||
Utils::printSafeJson($body)
|
Utils::printSafeJson($bodyParams)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isset($body[0])) {
|
|
||||||
$result = [];
|
|
||||||
foreach ($body as $index => $entry) {
|
|
||||||
$op = OperationParams::create($entry);
|
|
||||||
$result[] = $op;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = OperationParams::create($body);
|
|
||||||
}
|
|
||||||
} else if (stripos($contentType, 'application/x-www-form-urlencoded') !== false) {
|
} else if (stripos($contentType, 'application/x-www-form-urlencoded') !== false) {
|
||||||
$result = OperationParams::create($_POST);
|
$bodyParams = $_POST;
|
||||||
} else if (null === $contentType) {
|
} else if (null === $contentType) {
|
||||||
throw new Error('Missing "Content-Type" header');
|
throw new Error('Missing "Content-Type" header');
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unexpected content type: " . Utils::printSafeJson($contentType));
|
throw new Error("Unexpected content type: " . Utils::printSafeJson($contentType));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parseRequestParams($method, $bodyParams, $urlParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts PSR7 request to OperationParams[]
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return array|Helper
|
||||||
|
*/
|
||||||
|
public function parsePsrRequest(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
$contentType = $request->getHeader('content-type');
|
||||||
|
if (isset($contentType[0]) && $contentType[0] === 'application/graphql') {
|
||||||
|
$bodyParams = ['query' => $request->getBody()->getContents()];
|
||||||
|
} else {
|
||||||
|
$bodyParams = $request->getParsedBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parseRequestParams(
|
||||||
|
$request->getMethod(),
|
||||||
|
$bodyParams,
|
||||||
|
$request->getQueryParams()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses normalized request params and returns instance of OperationParams or array of OperationParams in
|
||||||
|
* case of batch operation.
|
||||||
|
*
|
||||||
|
* Returned value is a suitable input for `executeOperation` or `executeBatch` (if array)
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $bodyParams
|
||||||
|
* @param array $queryParams
|
||||||
|
* @return OperationParams|OperationParams[]
|
||||||
|
* @throws Error
|
||||||
|
*/
|
||||||
|
public function parseRequestParams($method, array $bodyParams, array $queryParams)
|
||||||
|
{
|
||||||
|
if ($method === 'GET') {
|
||||||
|
$result = OperationParams::create($queryParams, true);
|
||||||
|
} else if ($method === 'POST') {
|
||||||
|
if (isset($bodyParams[0])) {
|
||||||
|
$result = [];
|
||||||
|
foreach ($bodyParams as $index => $entry) {
|
||||||
|
$op = OperationParams::create($entry);
|
||||||
|
$result[] = $op;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = OperationParams::create($bodyParams);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('HTTP Method "' . $method . '" is not supported');
|
throw new Error('HTTP Method "' . $method . '" is not supported');
|
||||||
}
|
}
|
||||||
@ -258,7 +299,7 @@ class Helper
|
|||||||
/**
|
/**
|
||||||
* @return bool|string
|
* @return bool|string
|
||||||
*/
|
*/
|
||||||
public function readRawBody()
|
private function readRawBody()
|
||||||
{
|
{
|
||||||
return file_get_contents('php://input');
|
return file_get_contents('php://input');
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ namespace GraphQL\Server;
|
|||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Executor\ExecutionResult;
|
use GraphQL\Executor\ExecutionResult;
|
||||||
use GraphQL\Executor\Promise\Promise;
|
use GraphQL\Executor\Promise\Promise;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StandardServer
|
* Class StandardServer
|
||||||
@ -47,6 +48,22 @@ class StandardServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Executes GraphQL operation with given server configuration and returns execution result
|
||||||
|
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||||
|
*/
|
||||||
|
public function executePsrRequest(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
$parsedBody = $this->helper->parsePsrRequest($request);
|
||||||
|
return $this->executeRequest($parsedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes GraphQL operation with given server configuration and returns execution result
|
||||||
|
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||||
|
*
|
||||||
* @param OperationParams|OperationParams[] $parsedBody
|
* @param OperationParams|OperationParams[] $parsedBody
|
||||||
* @return ExecutionResult|ExecutionResult[]|Promise
|
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||||
* @throws InvariantViolation
|
* @throws InvariantViolation
|
||||||
|
Loading…
Reference in New Issue
Block a user