Skip to content

Commit e04d330

Browse files
committed
Server: send result for regular responses + prepare response for PSR7 request
1 parent b2ec265 commit e04d330

File tree

5 files changed

+131
-4
lines changed

5 files changed

+131
-4
lines changed

src/Server/Helper.php

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
use GraphQL\Utils\AST;
1515
use GraphQL\Utils\Utils;
1616
use GraphQL\Validator\DocumentValidator;
17+
use Psr\Http\Message\ResponseInterface;
1718
use Psr\Http\Message\ServerRequestInterface;
19+
use Psr\Http\Message\StreamInterface;
1820

1921
/**
2022
* Class Helper
@@ -131,7 +133,9 @@ private function promiseToExecuteOperation(PromiseAdapter $promiseAdapter, Serve
131133
return FormattedError::createFromException($e, true);
132134
};
133135
} else {
134-
$errorFormatter = $config->getErrorFormatter();
136+
$errorFormatter = $config->getErrorFormatter() ?: function($e) {
137+
return FormattedError::createFromException($e, false);
138+
};
135139
}
136140
$result->setErrorFormatter($errorFormatter);
137141
return $result;
@@ -264,6 +268,66 @@ public function parsePsrRequest(ServerRequestInterface $request)
264268
);
265269
}
266270

271+
/**
272+
* Converts query execution result to PSR response
273+
*
274+
* @param Promise|ExecutionResult|ExecutionResult[] $result
275+
* @param ResponseInterface $response
276+
* @param StreamInterface $writableBodyStream
277+
* @return Promise|ResponseInterface
278+
*/
279+
public function toPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
280+
{
281+
if ($result instanceof Promise) {
282+
return $result->then(function($actualResult) use ($response, $writableBodyStream) {
283+
return $this->doConvertToPsrResponse($actualResult, $response, $writableBodyStream);
284+
});
285+
} else {
286+
return $this->doConvertToPsrResponse($result, $response, $writableBodyStream);
287+
}
288+
}
289+
290+
private function doConvertToPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
291+
{
292+
$httpStatus = $this->resolveHttpStatus($result);
293+
294+
$result = json_encode($result);
295+
$writableBodyStream->write($result);
296+
297+
return $response
298+
->withStatus($httpStatus)
299+
->withHeader('Content-Type', 'application/json')
300+
->withBody($writableBodyStream);
301+
}
302+
303+
/**
304+
* @param Promise|ExecutionResult|ExecutionResult[] $result
305+
* @param bool $exitWhenDone
306+
*/
307+
public function sendResponse($result, $exitWhenDone = false)
308+
{
309+
if ($result instanceof Promise) {
310+
$result->then(function($actualResult) use ($exitWhenDone) {
311+
$this->doSendResponse($actualResult, $exitWhenDone);
312+
});
313+
} else {
314+
$this->doSendResponse($result, $exitWhenDone);
315+
}
316+
}
317+
318+
private function doSendResponse($result, $exitWhenDone)
319+
{
320+
$httpStatus = $this->resolveHttpStatus($result);
321+
$body = json_encode($result);
322+
323+
header('Content-Type: application/json', true, $httpStatus);
324+
echo $body;
325+
326+
if ($exitWhenDone) {
327+
exit;
328+
}
329+
}
330+
267331
/**
268332
* Parses normalized request params and returns instance of OperationParams or array of OperationParams in
269333
* case of batch operation.
@@ -347,4 +411,39 @@ public function validateOperationParams(OperationParams $params)
347411
}
348412
return $errors;
349413
}
414+
415+
/**
416+
* @param $result
417+
* @return int
418+
*/
419+
private function resolveHttpStatus($result)
420+
{
421+
if (is_array($result)) {
422+
Utils::each($tmp, function ($executionResult, $index) {
423+
if (!$executionResult instanceof ExecutionResult) {
424+
throw new InvariantViolation(sprintf(
425+
"Expecting every entry of batched query result to be instance of %s but entry at position %d is %s",
426+
ExecutionResult::class,
427+
$index,
428+
Utils::printSafe($executionResult)
429+
));
430+
}
431+
});
432+
$httpStatus = 200;
433+
} else {
434+
if (!$result instanceof ExecutionResult) {
435+
throw new InvariantViolation(sprintf(
436+
"Expecting query result to be instance of %s but got %s",
437+
ExecutionResult::class,
438+
Utils::printSafe($result)
439+
));
440+
}
441+
if ($result->data === null && !empty($result->errors)) {
442+
$httpStatus = 400;
443+
} else {
444+
$httpStatus = 200;
445+
}
446+
}
447+
return $httpStatus;
448+
}
350449
}

src/Server/ServerConfig.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static function create()
3535
/**
3636
* @var callable
3737
*/
38-
private $errorFormatter = [FormattedError::class, 'createFromException'];
38+
private $errorFormatter;
3939

4040
/**
4141
* @var bool

src/Server/StandardServer.php

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

911
/**
1012
* Class StandardServer
@@ -80,4 +82,30 @@ public function executeRequest($parsedBody = null)
8082
return $this->helper->executeOperation($this->config, $parsedBody);
8183
}
8284
}
85+
86+
/**
87+
* @param ServerRequestInterface $request
88+
* @param ResponseInterface $response
89+
* @param StreamInterface $writableBodyStream
90+
* @return ResponseInterface|Promise
91+
*/
92+
public function processPsrRequest(
93+
ServerRequestInterface $request,
94+
ResponseInterface $response,
95+
StreamInterface $writableBodyStream
96+
)
97+
{
98+
$result = $this->executePsrRequest($request);
99+
return $this->helper->toPsrResponse($result, $response, $writableBodyStream);
100+
}
101+
102+
/**
103+
* @param OperationParams|OperationParams[] $parsedBody
104+
* @param bool $exitWhenDone
105+
*/
106+
public function processRequest($parsedBody = null, $exitWhenDone = false)
107+
{
108+
$result = $this->executeRequest($parsedBody);
109+
$this->helper->sendResponse($result, $exitWhenDone);
110+
}
83111
}

tests/Server/QueryExecutionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ private function executeBatchedQuery(array $qs)
543543
{
544544
$batch = [];
545545
foreach ($qs as $params) {
546-
$batch[] = OperationParams::create($params, true);
546+
$batch[] = OperationParams::create($params);
547547
}
548548
$helper = new Helper();
549549
$result = $helper->executeBatch($this->config, $batch);

tests/Server/ServerConfigTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function testDefaults()
1515
$this->assertEquals(null, $config->getSchema());
1616
$this->assertEquals(null, $config->getContext());
1717
$this->assertEquals(null, $config->getRootValue());
18-
$this->assertEquals([FormattedError::class, 'createFromException'], $config->getErrorFormatter());
18+
$this->assertEquals(null, $config->getErrorFormatter());
1919
$this->assertEquals(null, $config->getPromiseAdapter());
2020
$this->assertEquals(null, $config->getValidationRules());
2121
$this->assertEquals(null, $config->getDefaultFieldResolver());

0 commit comments

Comments
 (0)