Drop support non pre-parsed PSR-7 request body

This revert #202 (commit 9d37f4c) because trying to parse PSR-7 request
was a mistake. The whole point of PSR-7 is to allow for interoperability
and be able to use specialized libs for body parsing (amongst many other
things). Trying to parse ourselves would be opening a can of worm if/when
other content types have to be supported. It is more correct and future
safe to require that the body is parsed before being passed to GraphQL.
This commit is contained in:
Adrien Crivelli 2017-12-21 15:01:57 +09:00
parent a3f18b51f7
commit 178b179db3
No known key found for this signature in database
GPG Key ID: B182FD79DC6DE92E
3 changed files with 31 additions and 30 deletions

View File

@ -493,21 +493,18 @@ class Helper
); );
} }
// Try parsing ourselves if PSR-7 implementation doesn't parse JSON automatically
if (is_array($bodyParams) && empty($bodyParams)) {
$bodyParams = json_decode($request->getBody(), true);
if (json_last_error()) {
throw new RequestError("Could not parse JSON: " . json_last_error_msg());
}
}
if (!is_array($bodyParams)) { if (!is_array($bodyParams)) {
throw new RequestError( throw new RequestError(
"GraphQL Server expects JSON object or array, but got " . "GraphQL Server expects JSON object or array, but got " .
Utils::printSafeJson($bodyParams) Utils::printSafeJson($bodyParams)
); );
} }
if (empty($bodyParams)) {
throw new InvariantViolation(
"PSR-7 request is expected to provide parsed body for \"application/json\" requests but got empty array"
);
}
} else { } else {
$bodyParams = $request->getParsedBody(); $bodyParams = $request->getParsedBody();

View File

@ -181,6 +181,20 @@ class RequestParsingTest extends \PHPUnit_Framework_TestCase
} }
} }
public function testFailsParsingNonPreParsedPsrRequest()
{
try {
$this->parsePsrRequest('application/json', json_encode([]));
$this->fail('Expected exception not thrown');
} catch (InvariantViolation $e) {
// Expecting parsing exception to be thrown somewhere else:
$this->assertEquals(
'PSR-7 request is expected to provide parsed body for "application/json" requests but got empty array',
$e->getMessage()
);
}
}
// There is no equivalent for psr request, because it should throw // There is no equivalent for psr request, because it should throw
public function testFailsParsingNonArrayOrObjectJsonRequest() public function testFailsParsingNonArrayOrObjectJsonRequest()
@ -242,15 +256,19 @@ class RequestParsingTest extends \PHPUnit_Framework_TestCase
public function testFailsOnMethodsOtherThanPostOrGet() public function testFailsOnMethodsOtherThanPostOrGet()
{ {
$body = [
'query' => '{my query}',
];
try { try {
$this->parseRawRequest('application/json', json_encode([]), "PUT"); $this->parseRawRequest('application/json', json_encode($body), "PUT");
$this->fail('Expected exception not thrown'); $this->fail('Expected exception not thrown');
} catch (RequestError $e) { } catch (RequestError $e) {
$this->assertEquals('HTTP Method "PUT" is not supported', $e->getMessage()); $this->assertEquals('HTTP Method "PUT" is not supported', $e->getMessage());
} }
try { try {
$this->parsePsrRequest('application/json', json_encode([]), "PUT"); $this->parsePsrRequest('application/json', json_encode($body), "PUT");
$this->fail('Expected exception not thrown'); $this->fail('Expected exception not thrown');
} catch (RequestError $e) { } catch (RequestError $e) {
$this->assertEquals('HTTP Method "PUT" is not supported', $e->getMessage()); $this->assertEquals('HTTP Method "PUT" is not supported', $e->getMessage());

View File

@ -43,9 +43,9 @@ class StandardServerTest extends TestCase
public function testSimplePsrRequestExecution() public function testSimplePsrRequestExecution()
{ {
$body = json_encode([ $body = [
'query' => '{f1}' 'query' => '{f1}'
]); ];
$expected = [ $expected = [
'data' => [ 'data' => [
@ -53,11 +53,8 @@ class StandardServerTest extends TestCase
] ]
]; ];
$preParsedRequest = $this->preparePsrRequest('application/json', $body, true); $request = $this->preparePsrRequest('application/json', $body);
$this->assertPsrRequestEquals($expected, $preParsedRequest); $this->assertPsrRequestEquals($expected, $request);
$notPreParsedRequest = $this->preparePsrRequest('application/json', $body, false);
$this->assertPsrRequestEquals($expected, $notPreParsedRequest);
} }
private function executePsrRequest($psrRequest) private function executePsrRequest($psrRequest)
@ -75,22 +72,11 @@ class StandardServerTest extends TestCase
return $result; return $result;
} }
private function preparePsrRequest($contentType, $content, $preParseBody) private function preparePsrRequest($contentType, $parsedBody)
{ {
$psrRequestBody = new PsrStreamStub();
$psrRequestBody->content = $content;
$psrRequest = new PsrRequestStub(); $psrRequest = new PsrRequestStub();
$psrRequest->headers['content-type'] = [$contentType]; $psrRequest->headers['content-type'] = [$contentType];
$psrRequest->method = 'POST'; $psrRequest->method = 'POST';
$psrRequest->body = $psrRequestBody;
if ($preParseBody && $contentType === 'application/json') {
$parsedBody = json_decode($content, true);
} else {
$parsedBody = [];
}
$psrRequest->parsedBody = $parsedBody; $psrRequest->parsedBody = $parsedBody;
return $psrRequest; return $psrRequest;
} }