Skip to content
Snippets Groups Projects
Commit 965ce571 authored by Thomas Tanghus's avatar Thomas Tanghus
Browse files

Modified PUT behaviour

Now only non-parable PUT requests return a stream resource.
parent 8035787c
No related branches found
No related tags found
No related merge requests found
...@@ -36,7 +36,6 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -36,7 +36,6 @@ class Request implements \ArrayAccess, \Countable, IRequest {
protected $allowedKeys = array( protected $allowedKeys = array(
'get', 'get',
'post', 'post',
'patch',
'files', 'files',
'server', 'server',
'env', 'env',
...@@ -69,7 +68,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -69,7 +68,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
// Only 'application/x-www-form-urlencoded' requests are automatically // Only 'application/x-www-form-urlencoded' requests are automatically
// transformed by PHP, 'application/json' must be decoded manually. // transformed by PHP, 'application/json' must be decoded manually.
if (isset($this->items['post']) if ($this->method === 'POST'
&& strpos($this->getHeader('Content-Type'), 'application/json') !== false && strpos($this->getHeader('Content-Type'), 'application/json') !== false
&& is_string($this->items['post'])) { && is_string($this->items['post'])) {
$this->items['params'] = $this->items['post'] = json_decode($this->items['post'], true); $this->items['params'] = $this->items['post'] = json_decode($this->items['post'], true);
...@@ -296,9 +295,9 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -296,9 +295,9 @@ class Request implements \ArrayAccess, \Countable, IRequest {
/** /**
* Returns the request body content. * Returns the request body content.
* *
* If the HTTP request method is PUT a stream resource is returned, otherwise an * If the HTTP request method is PUT and the body
* array or a string depending on the Content-Type. For "normal" use an array * not application/x-www-form-urlencoded or application/json a stream
* will be returned. * resource is returned, otherwise an array.
* *
* @return array|string|resource The request body content or a resource to read the body stream. * @return array|string|resource The request body content or a resource to read the body stream.
* *
...@@ -306,7 +305,10 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -306,7 +305,10 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*/ */
protected function getContent() { protected function getContent() {
if ($this->content === false && $this->method === 'PUT') { if ($this->content === false && $this->method === 'PUT') {
throw new \LogicException('"put" can only be accessed once.'); throw new \LogicException(
'"put" can only be accessed once if not '
. 'application/x-www-form-urlencoded or application/json.'
);
} }
if (defined('PHPUNIT_RUN') && PHPUNIT_RUN if (defined('PHPUNIT_RUN') && PHPUNIT_RUN
...@@ -316,7 +318,11 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -316,7 +318,11 @@ class Request implements \ArrayAccess, \Countable, IRequest {
$stream = 'php://input'; $stream = 'php://input';
} }
if ($this->method === 'PUT') { // If the content can't be parsed into an array then return a stream resource.
if ($this->method === 'PUT'
&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
&& strpos($this->getHeader('Content-Type'), 'application/json') === false
) {
$this->content = false; $this->content = false;
return fopen($stream, 'rb'); return fopen($stream, 'rb');
} }
...@@ -324,25 +330,23 @@ class Request implements \ArrayAccess, \Countable, IRequest { ...@@ -324,25 +330,23 @@ class Request implements \ArrayAccess, \Countable, IRequest {
if (is_null($this->content)) { if (is_null($this->content)) {
$this->content = file_get_contents($stream); $this->content = file_get_contents($stream);
if ($this->method === 'PATCH') { /*
/* * Normal jquery ajax requests are sent as application/x-www-form-urlencoded
* Normal jquery ajax requests are sent as application/x-www-form-urlencoded * and in $_GET and $_POST PHP transformes the data into an array.
* and in $_GET and $_POST PHP transformes the data into an array. * The first condition mimics this.
* The first condition mimics this. * The second condition allows for sending raw application/json data while
* The second condition allows for sending raw application/json data while * still getting the result as an array.
* still getting the result as an array. *
* */
*/ if (strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
if (strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { parse_str($this->content, $content);
parse_str($this->content, $content); if(is_array($content)) {
if(is_array($content)) { $this->content = $content;
$this->content = $content; }
} } elseif (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
} elseif (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { $content = json_decode($this->content, true);
$content = json_decode($this->content, true); if(is_array($content)) {
if(is_array($content)) { $this->content = $content;
$this->content = $content;
}
} }
} }
} }
......
...@@ -12,6 +12,18 @@ global $data; ...@@ -12,6 +12,18 @@ global $data;
class RequestTest extends \PHPUnit_Framework_TestCase { class RequestTest extends \PHPUnit_Framework_TestCase {
public function setUp() {
require_once __DIR__ . '/requeststream.php';
if (in_array('fakeinput', stream_get_wrappers())) {
stream_wrapper_unregister('fakeinput');
}
stream_wrapper_register('fakeinput', 'RequestStream');
}
public function tearDown() {
stream_wrapper_unregister('fakeinput');
}
public function testRequestAccessors() { public function testRequestAccessors() {
$vars = array( $vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
...@@ -34,7 +46,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase { ...@@ -34,7 +46,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase {
// Always returns null if variable not set. // Always returns null if variable not set.
$this->assertEquals(null, $request->{'flickname'}); $this->assertEquals(null, $request->{'flickname'});
require_once __DIR__ . '/requeststream.php';
} }
// urlParams has precedence over POST which has precedence over GET // urlParams has precedence over POST which has precedence over GET
...@@ -123,11 +134,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase { ...@@ -123,11 +134,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase {
global $data; global $data;
$data = http_build_query(array('name' => 'John Q. Public', 'nickname' => 'Joey'), '', '&'); $data = http_build_query(array('name' => 'John Q. Public', 'nickname' => 'Joey'), '', '&');
if (in_array('fakeinput', stream_get_wrappers())) {
stream_wrapper_unregister('fakeinput');
}
stream_wrapper_register('fakeinput', 'RequestStream');
$vars = array( $vars = array(
'patch' => $data, 'patch' => $data,
'method' => 'PATCH', 'method' => 'PATCH',
...@@ -141,21 +147,29 @@ class RequestTest extends \PHPUnit_Framework_TestCase { ...@@ -141,21 +147,29 @@ class RequestTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals('John Q. Public', $result['name']); $this->assertEquals('John Q. Public', $result['name']);
$this->assertEquals('Joey', $result['nickname']); $this->assertEquals('Joey', $result['nickname']);
stream_wrapper_unregister('fakeinput');
} }
public function testJsonPatch() { public function testJsonPatchAndPut() {
global $data; global $data;
$data = '{"name": "John Q. Public", "nickname": null}';
if (in_array('fakeinput', stream_get_wrappers())) { // PUT content
stream_wrapper_unregister('fakeinput'); $data = '{"name": "John Q. Public", "nickname": "Joey"}';
} $vars = array(
stream_wrapper_register('fakeinput', 'RequestStream'); 'method' => 'PUT',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
);
$request = new Request($vars);
$this->assertEquals('PUT', $request->method);
$result = $request->put;
$this->assertEquals('John Q. Public', $result['name']);
$this->assertEquals('Joey', $result['nickname']);
// PATCH content
$data = '{"name": "John Q. Public", "nickname": null}';
$vars = array( $vars = array(
'patch' => $data,
'method' => 'PATCH', 'method' => 'PATCH',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
); );
...@@ -167,19 +181,12 @@ class RequestTest extends \PHPUnit_Framework_TestCase { ...@@ -167,19 +181,12 @@ class RequestTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals('John Q. Public', $result['name']); $this->assertEquals('John Q. Public', $result['name']);
$this->assertEquals(null, $result['nickname']); $this->assertEquals(null, $result['nickname']);
stream_wrapper_unregister('fakeinput');
} }
public function testPutSteam() { public function testPutStream() {
global $data; global $data;
$data = file_get_contents(__DIR__ . '/../../../data/testimage.png'); $data = file_get_contents(__DIR__ . '/../../../data/testimage.png');
if (in_array('fakeinput', stream_get_wrappers())) {
stream_wrapper_unregister('fakeinput');
}
stream_wrapper_register('fakeinput', 'RequestStream');
$vars = array( $vars = array(
'put' => $data, 'put' => $data,
'method' => 'PUT', 'method' => 'PUT',
...@@ -195,7 +202,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase { ...@@ -195,7 +202,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase {
try { try {
$resource = $request->put; $resource = $request->put;
} catch(\LogicException $e) { } catch(\LogicException $e) {
stream_wrapper_unregister('fakeinput');
return; return;
} }
$this->fail('Expected LogicException.'); $this->fail('Expected LogicException.');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment