From 0d2fd2086746592edab064a72da082619a9f7993 Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 22:41:42 +0200 Subject: [PATCH 1/7] fix typo --- tests/helpers/RequestParserTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/helpers/RequestParserTest.php b/tests/helpers/RequestParserTest.php index 6410c78..e9c3025 100644 --- a/tests/helpers/RequestParserTest.php +++ b/tests/helpers/RequestParserTest.php @@ -349,7 +349,7 @@ public function testHasAttribute() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertTrue($requestParser->hasAttribute('foo')); $this->assertFalse($requestParser->hasAttribute('bar')); } @@ -363,7 +363,7 @@ public function testGetAttribute() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertSame('bar', $requestParser->getAttribute('foo')); } @@ -385,7 +385,7 @@ public function testHasRelationship() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertTrue($requestParser->hasRelationship('foo')); $this->assertFalse($requestParser->hasRelationship('bar')); } @@ -404,7 +404,7 @@ public function testGetRelationship() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertSame(['data' => ['type' => 'bar', 'id' => '42']], $requestParser->getRelationship('foo')); } @@ -419,7 +419,7 @@ public function testHasMeta() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertTrue($requestParser->hasMeta('foo')); $this->assertFalse($requestParser->hasMeta('bar')); } @@ -431,7 +431,7 @@ public function testGetMeta() { ], ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertSame('bar', $requestParser->getMeta('foo')); } @@ -456,7 +456,7 @@ public function testGetDocument() { 'foo' => 'bar', ]; - $requestParser = new RequestParser($selfLink='', $quaryParameters=[], $document); + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); $this->assertSame($document, $requestParser->getDocument()); } } From f3940324a28fe3254f04eb95e9cfea9cb09e26f9 Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 22:42:53 +0200 Subject: [PATCH 2/7] make properties protected to make it easier to extend --- src/helpers/RequestParser.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index 5ae8f25..eb25fbe 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -25,11 +25,11 @@ class RequestParser { 'useAnnotatedSortFields' => true, ]; /** @var string */ - private $selfLink = ''; + protected $selfLink = ''; /** @var array */ - private $queryParameters = []; + protected $queryParameters = []; /** @var array */ - private $document = []; + protected $document = []; /** * @param string $selfLink the uri used to make this request {@see getSelfLink()} From 1f01adf763cbd713f52da3b81a9a93e05e0c625c Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 22:44:21 +0200 Subject: [PATCH 3/7] add some more raw methods to get request details --- src/helpers/RequestParser.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index eb25fbe..243196e 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -150,6 +150,20 @@ public function getIncludePaths(array $options=[]) { return $restructured; } + /** + * @return boolean + */ + public function hasAnySparseFieldset() { + if (isset($this->queryParameters['fields']) === false) { + return false; + } + if ($this->queryParameters['fields'] === []) { + return false; + } + + return true; + } + /** * @param string $type * @return boolean @@ -319,6 +333,27 @@ public function getMeta($metaKey) { return $this->document['meta'][$metaKey]; } + /** + * @return boolean + */ + public function hasQueryParameters() { + return ($this->queryParameters !== []); + } + + /** + * @return array + */ + public function getQueryParameters() { + return $this->queryParameters; + } + + /** + * @return boolean + */ + public function hasDocument() { + return ($this->document !== []); + } + /** * @return array */ From dd41e8233eecbabcf5447a659c8083d49bfc5e26 Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 22:45:14 +0200 Subject: [PATCH 4/7] improve detection of request urls from different $_SERVER contexts --- src/helpers/RequestParser.php | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index 243196e..d7c1a5e 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -47,8 +47,33 @@ public function __construct($selfLink='', array $queryParameters=[], array $docu */ public static function fromSuperglobals() { $selfLink = ''; - if (isset($_SERVER['REQUEST_SCHEME']) && isset($_SERVER['HTTP_HOST']) && isset($_SERVER['REQUEST_URI'])) { - $selfLink = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; + + if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { + $selfLink .= $_SERVER['HTTP_X_FORWARDED_PROTO'].'://'; + } + elseif (isset($_SERVER['REQUEST_SCHEME'])) { + $selfLink .= $_SERVER['REQUEST_SCHEME'].'://'; + } + else { + $selfLink .= 'http://'; + } + + if (isset($_SERVER['HTTP_HOST'])) { + $selfLink .= $_SERVER['HTTP_HOST']; + } + elseif (isset($_SERVER['SCRIPT_URI'])) { + $startOfDomain = strpos($_SERVER['SCRIPT_URI'], '://'); + $endOfDomain = strpos($_SERVER['SCRIPT_URI'], '/', $startOfDomain); + $lengthOfDomain = ($endOfDomain - $startOfDomain); + $selfLink .= substr($_SERVER['SCRIPT_URI'], $startOfDomain, $lengthOfDomain); + } + + if (isset($_SERVER['REQUEST_URI'])) { + $selfLink .= $_SERVER['REQUEST_URI']; + } + elseif (isset($_SERVER['PATH_INFO']) && isset($_SERVER['QUERY_STRING'])) { + $selfLink .= $_SERVER['PATH_INFO']; + $selfLink .= ($_SERVER['QUERY_STRING'] !== '') ? '?'.$_SERVER['QUERY_STRING'] : ''; } $queryParameters = $_GET; From 66adc029e95c4d6ed7b530878fccc415a2a72f0c Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 23:08:29 +0200 Subject: [PATCH 5/7] extend request testing --- src/helpers/RequestParser.php | 2 +- tests/helpers/RequestParserTest.php | 91 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index d7c1a5e..60edf0c 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -62,7 +62,7 @@ public static function fromSuperglobals() { $selfLink .= $_SERVER['HTTP_HOST']; } elseif (isset($_SERVER['SCRIPT_URI'])) { - $startOfDomain = strpos($_SERVER['SCRIPT_URI'], '://'); + $startOfDomain = strpos($_SERVER['SCRIPT_URI'], '://') + strlen('://'); $endOfDomain = strpos($_SERVER['SCRIPT_URI'], '/', $startOfDomain); $lengthOfDomain = ($endOfDomain - $startOfDomain); $selfLink .= substr($_SERVER['SCRIPT_URI'], $startOfDomain, $lengthOfDomain); diff --git a/tests/helpers/RequestParserTest.php b/tests/helpers/RequestParserTest.php index e9c3025..44a4bca 100644 --- a/tests/helpers/RequestParserTest.php +++ b/tests/helpers/RequestParserTest.php @@ -54,6 +54,7 @@ public function testFromSuperglobals_HappyPath() { $this->assertSame('https://example.org/user/42?'.http_build_query($_GET), $requestParser->getSelfLink()); $this->assertTrue($requestParser->hasIncludePaths()); + $this->assertTrue($requestParser->hasAnySparseFieldset()); $this->assertTrue($requestParser->hasSparseFieldset('user')); $this->assertTrue($requestParser->hasSortFields()); $this->assertTrue($requestParser->hasPagination()); @@ -73,6 +74,10 @@ public function testFromSuperglobals_HappyPath() { $this->assertSame(['data' => ['type' => 'ship', 'id' => '42']], $requestParser->getRelationship('ship')); $this->assertSame(true, $requestParser->getMeta('lock')); + $this->assertTrue($requestParser->hasQueryParameters()); + $this->assertTrue($requestParser->hasDocument()); + + $this->assertSame($_GET, $requestParser->getQueryParameters()); $this->assertSame($_POST, $requestParser->getDocument()); } @@ -90,10 +95,33 @@ public function testFromSuperglobals_WithPhpInputStream() { $this->assertSame([], $requestParser->getDocument()); } + public function testFromSuperglobals_WithForwarding() { + unset($_SERVER['REQUEST_SCHEME']); + unset($_SERVER['HTTP_HOST']); + unset($_SERVER['REQUEST_URI']); + unset($_SERVER['CONTENT_TYPE']); + + $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https'; + $_SERVER['SCRIPT_URI'] = 'http://example.org/users'; + $_SERVER['PATH_INFO'] = '/users'; + $_SERVER['QUERY_STRING'] = 'include=foo'; + + $_GET = []; + $_POST = []; + + $requestParser = RequestParser::fromSuperglobals(); + + $this->assertSame('https://example.org/users?include=foo', $requestParser->getSelfLink()); + } + public function testFromSuperglobals_WithoutServerContext() { + unset($_SERVER['HTTP_X_FORWARDED_PROTO']); unset($_SERVER['REQUEST_SCHEME']); unset($_SERVER['HTTP_HOST']); + unset($_SERVER['SCRIPT_URI']); unset($_SERVER['REQUEST_URI']); + unset($_SERVER['PATH_INFO']); + unset($_SERVER['QUERY_STRING']); unset($_SERVER['CONTENT_TYPE']); $_GET = []; @@ -145,6 +173,7 @@ public function testFromPsrRequest_WithRequestInterface() { $this->assertSame('https://example.org/user/42?'.http_build_query($queryParameters), $requestParser->getSelfLink()); $this->assertTrue($requestParser->hasIncludePaths()); + $this->assertTrue($requestParser->hasAnySparseFieldset()); $this->assertTrue($requestParser->hasSparseFieldset('user')); $this->assertTrue($requestParser->hasSortFields()); $this->assertTrue($requestParser->hasPagination()); @@ -164,6 +193,10 @@ public function testFromPsrRequest_WithRequestInterface() { $this->assertSame(['data' => ['type' => 'ship', 'id' => '42']], $requestParser->getRelationship('ship')); $this->assertSame(true, $requestParser->getMeta('lock')); + $this->assertTrue($requestParser->hasQueryParameters()); + $this->assertTrue($requestParser->hasDocument()); + + $this->assertSame($queryParameters, $requestParser->getQueryParameters()); $this->assertSame($document, $requestParser->getDocument()); } @@ -253,6 +286,20 @@ public function testGetIncludePaths_Raw() { $this->assertSame(['foo', 'bar', 'baz.baf'], $requestParser->getIncludePaths($options)); } + public function testHasAnySparseFieldset() { + $queryParameters = []; + $requestParser = new RequestParser($selfLink='', $queryParameters); + $this->assertFalse($requestParser->hasAnySparseFieldset()); + + $queryParameters = ['fields' => []]; + $requestParser = new RequestParser($selfLink='', $queryParameters); + $this->assertFalse($requestParser->hasAnySparseFieldset()); + + $queryParameters = ['fields' => ['foo' => 'bar', 'baf' => 'baz']]; + $requestParser = new RequestParser($selfLink='', $queryParameters); + $this->assertTrue($requestParser->hasAnySparseFieldset()); + } + public function testHasSparseFieldset() { $requestParser = new RequestParser(); $this->assertFalse($requestParser->hasSparseFieldset('foo')); @@ -435,6 +482,50 @@ public function testGetMeta() { $this->assertSame('bar', $requestParser->getMeta('foo')); } + public function testHasQueryParameters() { + $queryParameters = []; + $requestParser = new RequestParser($selfLink='', $queryParameters, $document=[]); + $this->assertFalse($requestParser->hasQueryParameters()); + + $queryParameters = [ + 'filter' => '42', + ]; + $requestParser = new RequestParser($selfLink='', $queryParameters, $document=[]); + $this->assertTrue($requestParser->hasQueryParameters()); + } + + public function testGetQueryParameters() { + $queryParameters = [ + 'include' => 'ship,ship.wing', + 'fields' => [ + 'user' => 'name,location', + ], + 'sort' => 'name,-location', + 'page' => [ + 'number' => '2', + 'size' => '10', + ], + 'filter' => '42', + ]; + + $requestParser = new RequestParser($selfLink='', $queryParameters, $document=[]); + $this->assertSame($queryParameters, $requestParser->getQueryParameters()); + } + + public function testHasDocument() { + $document = []; + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); + $this->assertFalse($requestParser->hasDocument()); + + $document = [ + 'meta' => [ + 'foo' => 'bar', + ], + ]; + $requestParser = new RequestParser($selfLink='', $queryParameters=[], $document); + $this->assertTrue($requestParser->hasDocument()); + } + public function testGetDocument() { $document = [ 'data' => [ From 6663ff69b3d7f332c4b87f6553c954b600e134d1 Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 25 Apr 2021 23:10:34 +0200 Subject: [PATCH 6/7] add new methods to example --- examples/request_superglobals.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/request_superglobals.php b/examples/request_superglobals.php index fff5992..fc4f02a 100644 --- a/examples/request_superglobals.php +++ b/examples/request_superglobals.php @@ -62,6 +62,7 @@ // useful for determining how to process the request (list/get/create/update) var_dump($requestParser->hasIncludePaths()); +var_dump($requestParser->hasAnySparseFieldset()); var_dump($requestParser->hasSparseFieldset('user')); var_dump($requestParser->hasSortFields()); var_dump($requestParser->hasPagination()); @@ -84,5 +85,10 @@ var_dump($requestParser->getRelationship('ship')); var_dump($requestParser->getMeta('lock')); -// get the full document for custom processing +// useful for determining how to process the request (list/get/create/update) +var_dump($requestParser->hasQueryParameters()); +var_dump($requestParser->hasDocument()); + +// get the full query parameters or document for custom processing +var_dump($requestParser->getQueryParameters()); var_dump($requestParser->getDocument()); From f70f80179778dab31ea11a62fa156dcc84fa01fa Mon Sep 17 00:00:00 2001 From: Lode Claassen Date: Sun, 16 May 2021 16:11:11 +0200 Subject: [PATCH 7/7] can't actually pass an empty array as query value --- src/helpers/RequestParser.php | 9 +-------- tests/helpers/RequestParserTest.php | 5 +++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/helpers/RequestParser.php b/src/helpers/RequestParser.php index 60edf0c..6e9f468 100644 --- a/src/helpers/RequestParser.php +++ b/src/helpers/RequestParser.php @@ -179,14 +179,7 @@ public function getIncludePaths(array $options=[]) { * @return boolean */ public function hasAnySparseFieldset() { - if (isset($this->queryParameters['fields']) === false) { - return false; - } - if ($this->queryParameters['fields'] === []) { - return false; - } - - return true; + return (isset($this->queryParameters['fields'])); } /** diff --git a/tests/helpers/RequestParserTest.php b/tests/helpers/RequestParserTest.php index 44a4bca..0ec772b 100644 --- a/tests/helpers/RequestParserTest.php +++ b/tests/helpers/RequestParserTest.php @@ -291,9 +291,10 @@ public function testHasAnySparseFieldset() { $requestParser = new RequestParser($selfLink='', $queryParameters); $this->assertFalse($requestParser->hasAnySparseFieldset()); - $queryParameters = ['fields' => []]; + // not allowed, but possible + $queryParameters = ['fields' => '']; $requestParser = new RequestParser($selfLink='', $queryParameters); - $this->assertFalse($requestParser->hasAnySparseFieldset()); + $this->assertTrue($requestParser->hasAnySparseFieldset()); $queryParameters = ['fields' => ['foo' => 'bar', 'baf' => 'baz']]; $requestParser = new RequestParser($selfLink='', $queryParameters);