Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/Http/HttpCodeDecider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace TheCodingMachine\GraphQLite\Http;

use GraphQL\Executor\ExecutionResult;
use function max;

class HttpCodeDecider implements HttpCodeDeciderInterface
{
/**
* Decides the HTTP status code based on the answer.
*
* @see https://github.com/APIs-guru/graphql-over-http#status-codes
*/
public function decideHttpStatusCode(ExecutionResult $result): int
{
// If the data entry in the response has any value other than null (when the operation has successfully executed without error) then the response should use the 200 (OK) status code.
if ($result->data !== null && empty($result->errors)) {
return 200;
}

$status = 0;
// There might be many errors. Let's return the highest code we encounter.
foreach ($result->errors as $error) {
$wrappedException = $error->getPrevious();
if ($wrappedException !== null) {
$code = $wrappedException->getCode();
if ($code < 400 || $code >= 600) {
// The exception code is not a valid HTTP code. Let's ignore it
continue;
}
} else {
$code = 400;
}
$status = max($status, $code);
}

// If exceptions have been thrown and they have not a "HTTP like code", let's throw a 500.
if ($status < 200) {
$status = 500;
}

return $status;
}
}
17 changes: 17 additions & 0 deletions src/Http/HttpCodeDeciderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace TheCodingMachine\GraphQLite\Http;

use GraphQL\Executor\ExecutionResult;

interface HttpCodeDeciderInterface
{
/**
* Decides the HTTP status code based on the answer.
*
* @see https://github.com/APIs-guru/graphql-over-http#status-codes
*/
public function decideHttpStatusCode(ExecutionResult $result): int;
}
44 changes: 44 additions & 0 deletions tests/Http/HttpCodeDeciderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace TheCodingMachine\GraphQLite\Http;

use Exception;
use GraphQL\Error\Error;
use GraphQL\Executor\ExecutionResult;
use PHPUnit\Framework\TestCase;

class HttpCodeDeciderTest extends TestCase
{

public function testDecideHttpStatusCode(): void
{
$codeDecider = new HttpCodeDecider();

$executionResult = new ExecutionResult(['someData'], []);

$this->assertSame(200, $codeDecider->decideHttpStatusCode($executionResult));

$graphqlError = new Error('Foo');

$exception = new Exception('foo', 0);
$errorCode0 = new Error('Foo', null, null, null, null, $exception);

$exception401 = new Exception('foo', 401);
$errorCode401 = new Error('Foo', null, null, null, null, $exception401);

$exception404 = new Exception('foo', 404);
$errorCode404 = new Error('Foo', null, null, null, null, $exception404);

$exception600 = new Exception('foo', 600);
$errorCode600 = new Error('Foo', null, null, null, null, $exception600);

$executionResult = new ExecutionResult(null, [ $errorCode0 ]);
$this->assertSame(500, $codeDecider->decideHttpStatusCode($executionResult));

$executionResult = new ExecutionResult(['foo'], [ $errorCode401, $errorCode404, $errorCode600 ]);
$this->assertSame(404, $codeDecider->decideHttpStatusCode($executionResult));

$executionResult = new ExecutionResult(null, [ $graphqlError ]);
$this->assertSame(400, $codeDecider->decideHttpStatusCode($executionResult));
}
}