Skip to content

Commit

Permalink
Add PSR7 body methods.
Browse files Browse the repository at this point in the history
Add the `withBody` and `getBody` methods. Internally the input parsing
has been replaced with streams. This requires changing some internal
state and deprecating setInput().
  • Loading branch information
markstory committed Sep 8, 2016
1 parent 0010c72 commit 169ee49
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 13 deletions.
60 changes: 47 additions & 13 deletions src/Network/Request.php
Expand Up @@ -20,7 +20,10 @@
use Cake\Network\Exception\MethodNotAllowedException;
use Cake\Utility\Hash;
use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface;
use Zend\Diactoros\PhpInputStream;
use Zend\Diactoros\Stream;
use Zend\Diactoros\UploadedFile;

/**
Expand Down Expand Up @@ -149,12 +152,11 @@ class Request implements ArrayAccess
protected $_detectorCache = [];

/**
* Copy of php://input. Since this stream can only be read once in most SAPI's
* keep a copy of it so users don't need to know about that detail.
* Request body stream. Contains php://input unless `input` constructor option is used.
*
* @var string
* @var \Psr\Http\Message\StreamInterface
*/
protected $_input = '';
protected $stream;

/**
* Instance of a Session object relative to this request
Expand Down Expand Up @@ -280,11 +282,17 @@ protected function _setConfig($config)
$this->cookies = $config['cookies'];
$this->here = $this->base . '/' . $this->url;
$this->webroot = $config['webroot'];

$this->_environment = $config['environment'];

if (isset($config['input'])) {
$this->_input = $config['input'];
$stream = new Stream('php://memory', 'rw');
$stream->write($config['input']);
$stream->rewind();
} else {
$stream = new PhpInputStream();
}
$this->stream = $stream;

$config['post'] = $this->_processPost($config['post']);
$this->data = $this->_processFiles($config['post'], $config['files']);
$this->query = $this->_processGet($config['query']);
Expand Down Expand Up @@ -1405,16 +1413,14 @@ public function param($name)
* @param string|null $callback A decoding callback that will convert the string data to another
* representation. Leave empty to access the raw input data. You can also
* supply additional parameters for the decoding callback using var args, see above.
* @param array ...$args The additional arguments
* @return string The decoded/processed request data.
*/
public function input($callback = null)
public function input($callback = null, ...$args)
{
$input = $this->_readInput();
$args = func_get_args();
if (!empty($args)) {
$callback = array_shift($args);
$input = $this->stream->getContents();
if ($callback) {
array_unshift($args, $input);

return call_user_func_array($callback, $args);
}

Expand Down Expand Up @@ -1573,10 +1579,14 @@ protected function _readInput()
*
* @param string $input A string to replace original parsed data from input()
* @return void
* @deprecated 3.4.0 This method will be removed in 4.0.0. Use withBody() instead.
*/
public function setInput($input)
{
$this->_input = $input;
$stream = new Stream('php://memory', 'rw');
$stream->write($input);
$stream->rewind();
$this->stream = $stream;
}

/**
Expand Down Expand Up @@ -1756,6 +1766,30 @@ protected function validateUploadedFiles(array $uploadedFiles, $path)
}
}

/**
* Gets the body of the message.
*
* @return \Psr\Http\Message\StreamInterface Returns the body as a stream.
*/
public function getBody()
{
return $this->stream;
}

/**
* Return an instance with the specified message body.
*
* @param \Psr\Http\Message\StreamInterface $body The new request body
* @return static
*/
public function withBody(StreamInterface $body)
{
$new = clone $this;
$new->stream = $body;

return $new;
}

/**
* Array access read implementation
*
Expand Down
23 changes: 23 additions & 0 deletions tests/TestCase/Network/RequestTest.php
Expand Up @@ -2628,6 +2628,29 @@ public function testInputDecodeExtraParams()
*/
public function testGetBody()
{
$request = new Request([
'input' => 'key=val&some=data'
]);
$result = $request->getBody();
$this->assertInstanceOf('Psr\Http\Message\StreamInterface', $result);
$this->assertEquals('key=val&some=data', $result->getContents());
}

/**
* Test withBody
*
* @return void
*/
public function testWithBody()
{
$request = new Request([
'input' => 'key=val&some=data'
]);
$body = $this->getMockBuilder('Psr\Http\Message\StreamInterface')->getMock();
$new = $request->withBody($body);
$this->assertNotSame($new, $request);
$this->assertNotSame($body, $request->getBody());
$this->assertSame($body, $new->getBody());
}

/**
Expand Down

0 comments on commit 169ee49

Please sign in to comment.