Skip to content

Commit

Permalink
Merge pull request #345 from clue-labs/headers
Browse files Browse the repository at this point in the history
Minor internal refactoring to apply server params during request ctor
  • Loading branch information
jsor committed Jun 14, 2019
2 parents c02fc4b + 29741b0 commit 809a514
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 52 deletions.
13 changes: 0 additions & 13 deletions src/Io/RequestHeaderParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,6 @@ private function parseRequest($headers)
);
$request = $request->withRequestTarget($target);

// Add query params
$queryString = $request->getUri()->getQuery();
if ($queryString !== '') {
$queryParams = array();
\parse_str($queryString, $queryParams);
$request = $request->withQueryParams($queryParams);
}

$cookies = ServerRequest::parseCookie($request->getHeaderLine('Cookie'));
if ($cookies !== false) {
$request = $request->withCookieParams($cookies);
}

// re-apply actual request target from above
if ($originalTarget !== null) {
$request = $request->withUri(
Expand Down
18 changes: 12 additions & 6 deletions src/Io/ServerRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ public function __construct(
) {
$this->serverParams = $serverParams;
parent::__construct($method, $uri, $headers, $body, $protocolVersion);

$query = $this->getUri()->getQuery();
if ($query !== '') {
\parse_str($query, $this->queryParams);
}

$this->cookies = $this->parseCookie($this->getHeaderLine('Cookie'));
}

public function getServerParams()
Expand Down Expand Up @@ -134,17 +141,16 @@ public function withoutAttribute($name)
}

/**
* @internal
* @param string $cookie
* @return boolean|mixed[]
* @return array
*/
public static function parseCookie($cookie)
private function parseCookie($cookie)
{
// PSR-7 `getHeaderLine('Cookies')` will return multiple
// PSR-7 `getHeaderLine('Cookie')` will return multiple
// cookie header comma-seperated. Multiple cookie headers
// are not allowed according to https://tools.ietf.org/html/rfc6265#section-5.4
if (\strpos($cookie, ',') !== false) {
return false;
if ($cookie === '' || \strpos($cookie, ',') !== false) {
return array();
}

$cookieArray = \explode(';', $cookie);
Expand Down
136 changes: 103 additions & 33 deletions tests/Io/ServerRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ public function testWithoutAttribute()
$this->assertEquals(array('test' => 'nice'), $request->getAttributes());
}

public function testGetQueryParamsFromConstructorUri()
{
$this->request = new ServerRequest('GET', 'http://localhost/?test=world');

$this->assertEquals(array('test' => 'world'), $this->request->getQueryParams());
}

public function testWithCookieParams()
{
$request = $this->request->withCookieParams(array('test' => 'world'));
Expand All @@ -62,6 +69,13 @@ public function testWithCookieParams()
$this->assertEquals(array('test' => 'world'), $request->getCookieParams());
}

public function testGetQueryParamsFromConstructorUriUrlencoded()
{
$this->request = new ServerRequest('GET', 'http://localhost/?test=hello+world%21');

$this->assertEquals(array('test' => 'hello world!'), $this->request->getQueryParams());
}

public function testWithQueryParams()
{
$request = $this->request->withQueryParams(array('test' => 'world'));
Expand All @@ -70,6 +84,14 @@ public function testWithQueryParams()
$this->assertEquals(array('test' => 'world'), $request->getQueryParams());
}

public function testWithQueryParamsWithoutSpecialEncoding()
{
$request = $this->request->withQueryParams(array('test' => 'hello world!'));

$this->assertNotSame($request, $this->request);
$this->assertEquals(array('test' => 'hello world!'), $request->getQueryParams());
}

public function testWithUploadedFiles()
{
$request = $this->request->withUploadedFiles(array('test' => 'world'));
Expand Down Expand Up @@ -109,85 +131,133 @@ public function testServerRequestParameter()

public function testParseSingleCookieNameValuePairWillReturnValidArray()
{
$cookieString = 'hello=world';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'world'), $cookies);
}

public function testParseMultipleCookieNameValuePaiWillReturnValidArray()
public function testParseMultipleCookieNameValuePairWillReturnValidArray()
{
$cookieString = 'hello=world; test=abc';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world; test=abc')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'world', 'test' => 'abc'), $cookies);
}

public function testParseMultipleCookieNameValuePairWillReturnFalse()
public function testParseMultipleCookieHeadersAreNotAllowedAndWillReturnEmptyArray()
{
// Could be done through multiple 'Cookie' headers
// getHeaderLine('Cookie') will return a value seperated by comma
// e.g.
// GET / HTTP/1.1\r\n
// Host: test.org\r\n
// Cookie: hello=world\r\n
// Cookie: test=abc\r\n\r\n
$cookieString = 'hello=world,test=abc';
$cookies = ServerRequest::parseCookie($cookieString);
$this->assertEquals(false, $cookies);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => array('hello=world', 'test=abc'))
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array(), $cookies);
}

public function testOnlyFirstSetWillBeAddedToCookiesArray()
public function testMultipleCookiesWithSameNameWillReturnLastValue()
{
$cookieString = 'hello=world; hello=abc';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world; hello=abc')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'abc'), $cookies);
}

public function testOtherEqualSignsWillBeAddedToValueAndWillReturnValidArray()
{
$cookieString = 'hello=world=test=php';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world=test=php')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'world=test=php'), $cookies);
}

public function testSingleCookieValueInCookiesReturnsEmptyArray()
{
$cookieString = 'world';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'world')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array(), $cookies);
}

public function testSingleMutlipleCookieValuesReturnsEmptyArray()
{
$cookieString = 'world; test';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'world; test')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array(), $cookies);
}

public function testSingleValueIsValidInMultipleValueCookieWillReturnValidArray()
{
$cookieString = 'world; test=php';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'world; test=php')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('test' => 'php'), $cookies);
}

public function testUrlEncodingForValueWillReturnValidArray()
{
$cookieString = 'hello=world%21; test=100%25%20coverage';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world%21; test=100%25%20coverage')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'world!', 'test' => '100% coverage'), $cookies);
}

public function testUrlEncodingForKeyWillReturnValidArray()
{
$cookieString = 'react%3Bphp=is%20great';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'react%3Bphp=is%20great')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('react;php' => 'is great'), $cookies);
}

public function testCookieWithoutSpaceAfterSeparatorWillBeAccepted()
{
$cookieString = 'hello=world;react=php';
$cookies = ServerRequest::parseCookie($cookieString);
$this->request = new ServerRequest(
'GET',
'http://localhost',
array('Cookie' => 'hello=world;react=php')
);

$cookies = $this->request->getCookieParams();
$this->assertEquals(array('hello' => 'world', 'react' => 'php'), $cookies);
}
}

0 comments on commit 809a514

Please sign in to comment.