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
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);
}
}