Skip to content

Commit b2ec265

Browse files
committed
Server: ability to execute PSR7 request
1 parent 87c812b commit b2ec265

File tree

2 files changed

+84
-26
lines changed

2 files changed

+84
-26
lines changed

src/Server/Helper.php

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use GraphQL\Utils\AST;
1515
use GraphQL\Utils\Utils;
1616
use GraphQL\Validator\DocumentValidator;
17+
use Psr\Http\Message\ServerRequestInterface;
1718

1819
/**
1920
* Class Helper
@@ -146,12 +147,8 @@ private function promiseToExecuteOperation(PromiseAdapter $promiseAdapter, Serve
146147
* @throws Error
147148
* @throws InvariantViolation
148149
*/
149-
public function loadPersistedQuery(ServerConfig $config, OperationParams $op)
150+
private function loadPersistedQuery(ServerConfig $config, OperationParams $op)
150151
{
151-
if (!$op->queryId) {
152-
throw new InvariantViolation("Could not load persisted query: queryId is not set");
153-
}
154-
155152
// Load query if we got persisted query id:
156153
$loader = $config->getPersistentQueryLoader();
157154

@@ -177,7 +174,7 @@ public function loadPersistedQuery(ServerConfig $config, OperationParams $op)
177174
* @param OperationParams $params
178175
* @return array
179176
*/
180-
public function resolveValidationRules(ServerConfig $config, OperationParams $params)
177+
private function resolveValidationRules(ServerConfig $config, OperationParams $params)
181178
{
182179
// Allow customizing validation rules per operation:
183180
$validationRules = $config->getValidationRules();
@@ -197,8 +194,8 @@ public function resolveValidationRules(ServerConfig $config, OperationParams $pa
197194
}
198195

199196
/**
200-
* Parses HTTP request and returns GraphQL QueryParams contained in this request.
201-
* For batched requests it returns an array of QueryParams.
197+
* Parses HTTP request and returns GraphQL OperationParams contained in this request.
198+
* For batched requests it returns an array of OperationParams.
202199
*
203200
* This function doesn't check validity of these params.
204201
*
@@ -211,44 +208,88 @@ public function resolveValidationRules(ServerConfig $config, OperationParams $pa
211208
public function parseHttpRequest(callable $readRawBodyFn = null)
212209
{
213210
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null;
211+
$bodyParams = [];
212+
$urlParams = $_GET;
214213

215-
if ($method === 'GET') {
216-
$result = OperationParams::create($_GET, true);
217-
} else if ($method === 'POST') {
214+
if ($method === 'POST') {
218215
$contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : null;
219216

220217
if (stripos($contentType, 'application/graphql') !== false) {
221218
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
222-
$result = OperationParams::create(['query' => $rawBody ?: '']);
219+
$bodyParams = ['query' => $rawBody ?: ''];
223220
} else if (stripos($contentType, 'application/json') !== false) {
224221
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
225-
$body = json_decode($rawBody ?: '', true);
222+
$bodyParams = json_decode($rawBody ?: '', true);
226223

227224
if (json_last_error()) {
228225
throw new Error("Could not parse JSON: " . json_last_error_msg());
229226
}
230-
if (!is_array($body)) {
227+
if (!is_array($bodyParams)) {
231228
throw new Error(
232229
"GraphQL Server expects JSON object or array, but got " .
233-
Utils::printSafeJson($body)
230+
Utils::printSafeJson($bodyParams)
234231
);
235232
}
236-
if (isset($body[0])) {
237-
$result = [];
238-
foreach ($body as $index => $entry) {
239-
$op = OperationParams::create($entry);
240-
$result[] = $op;
241-
}
242-
} else {
243-
$result = OperationParams::create($body);
244-
}
245233
} else if (stripos($contentType, 'application/x-www-form-urlencoded') !== false) {
246-
$result = OperationParams::create($_POST);
234+
$bodyParams = $_POST;
247235
} else if (null === $contentType) {
248236
throw new Error('Missing "Content-Type" header');
249237
} else {
250238
throw new Error("Unexpected content type: " . Utils::printSafeJson($contentType));
251239
}
240+
}
241+
242+
return $this->parseRequestParams($method, $bodyParams, $urlParams);
243+
}
244+
245+
/**
246+
* Converts PSR7 request to OperationParams[]
247+
*
248+
* @param ServerRequestInterface $request
249+
* @return array|Helper
250+
*/
251+
public function parsePsrRequest(ServerRequestInterface $request)
252+
{
253+
$contentType = $request->getHeader('content-type');
254+
if (isset($contentType[0]) && $contentType[0] === 'application/graphql') {
255+
$bodyParams = ['query' => $request->getBody()->getContents()];
256+
} else {
257+
$bodyParams = $request->getParsedBody();
258+
}
259+
260+
return $this->parseRequestParams(
261+
$request->getMethod(),
262+
$bodyParams,
263+
$request->getQueryParams()
264+
);
265+
}
266+
267+
/**
268+
* Parses normalized request params and returns instance of OperationParams or array of OperationParams in
269+
* case of batch operation.
270+
*
271+
* Returned value is a suitable input for `executeOperation` or `executeBatch` (if array)
272+
*
273+
* @param string $method
274+
* @param array $bodyParams
275+
* @param array $queryParams
276+
* @return OperationParams|OperationParams[]
277+
* @throws Error
278+
*/
279+
public function parseRequestParams($method, array $bodyParams, array $queryParams)
280+
{
281+
if ($method === 'GET') {
282+
$result = OperationParams::create($queryParams, true);
283+
} else if ($method === 'POST') {
284+
if (isset($bodyParams[0])) {
285+
$result = [];
286+
foreach ($bodyParams as $index => $entry) {
287+
$op = OperationParams::create($entry);
288+
$result[] = $op;
289+
}
290+
} else {
291+
$result = OperationParams::create($bodyParams);
292+
}
252293
} else {
253294
throw new Error('HTTP Method "' . $method . '" is not supported');
254295
}
@@ -258,7 +299,7 @@ public function parseHttpRequest(callable $readRawBodyFn = null)
258299
/**
259300
* @return bool|string
260301
*/
261-
public function readRawBody()
302+
private function readRawBody()
262303
{
263304
return file_get_contents('php://input');
264305
}

src/Server/StandardServer.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use GraphQL\Error\InvariantViolation;
55
use GraphQL\Executor\ExecutionResult;
66
use GraphQL\Executor\Promise\Promise;
7+
use Psr\Http\Message\ServerRequestInterface;
78

89
/**
910
* Class StandardServer
@@ -47,6 +48,22 @@ protected function __construct(ServerConfig $config)
4748
}
4849

4950
/**
51+
* Executes GraphQL operation with given server configuration and returns execution result
52+
* (or promise when promise adapter is different from SyncPromiseAdapter)
53+
*
54+
* @param ServerRequestInterface $request
55+
* @return ExecutionResult|ExecutionResult[]|Promise
56+
*/
57+
public function executePsrRequest(ServerRequestInterface $request)
58+
{
59+
$parsedBody = $this->helper->parsePsrRequest($request);
60+
return $this->executeRequest($parsedBody);
61+
}
62+
63+
/**
64+
* Executes GraphQL operation with given server configuration and returns execution result
65+
* (or promise when promise adapter is different from SyncPromiseAdapter)
66+
*
5067
* @param OperationParams|OperationParams[] $parsedBody
5168
* @return ExecutionResult|ExecutionResult[]|Promise
5269
* @throws InvariantViolation

0 commit comments

Comments
 (0)