Skip to content

Commit

Permalink
Add reusable RequestBody
Browse files Browse the repository at this point in the history
This copies the php://input stream to a php://temp stream that can be rewound and read multiple times so that the raw request body is not cannabilised by the first middleware to read it. Also automatically rewinds the request body after reading it in Request::getMethod() on POST so the “first” call to getContents() within the App invocation is not empty.

Should resolve #1386
  • Loading branch information
opengeek committed Aug 2, 2015
1 parent 1ca34b3 commit 39d12e5
Show file tree
Hide file tree
Showing 6 changed files with 393 additions and 45 deletions.
8 changes: 6 additions & 2 deletions Slim/Http/Request.php
Expand Up @@ -155,12 +155,12 @@ public static function createFromEnvironment(Environment $environment)
$headers = Headers::createFromEnvironment($environment);
$cookies = Cookies::parseHeader($headers->get('Cookie', []));
$serverParams = $environment->all();
$body = new Body(fopen('php://input', 'r'));
$body = new RequestBody();
$uploadedFiles = UploadedFile::createFromEnvironment($environment);

$request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles);

if ($request->isPost() &&
if ($method === 'POST' &&
in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data'])
) {
// parsed body must be $_POST
Expand Down Expand Up @@ -303,6 +303,10 @@ public function getMethod()
} elseif (is_array($body) && isset($body['_METHOD'])) {
$this->method = $this->filterMethod($body['_METHOD']);
}

if ($this->getBody()->eof()) {
$this->getBody()->rewind();
}
}
}

Expand Down
27 changes: 27 additions & 0 deletions Slim/Http/RequestBody.php
@@ -0,0 +1,27 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/codeguy/Slim/blob/master/LICENSE (MIT License)
*/
namespace Slim\Http;

/**
* Provides a PSR-7 implementation of a reusable raw request body
*/
class RequestBody extends Body
{
/**
* Create a new RequestBody.
*/
public function __construct()
{
$stream = fopen('php://temp', 'w+');
stream_copy_to_stream(fopen('php://input', 'r'), $stream);
rewind($stream);

parent::__construct($stream);
}
}
32 changes: 16 additions & 16 deletions tests/AppTest.php
Expand Up @@ -10,7 +10,7 @@
use \Slim\App;
use \Slim\Http\Environment;
use \Slim\Http\Uri;
use \Slim\Http\Body;
use \Slim\Http\RequestBody;
use \Slim\Http\Headers;
use \Slim\Http\Request;
use \Slim\Http\Response;
Expand Down Expand Up @@ -238,7 +238,7 @@ public function testInvokeReturnMethodNotAllowed()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('POST', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -270,7 +270,7 @@ public function testInvokeWithMatchingRoute()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -298,7 +298,7 @@ public function testInvokeWithMatchingRouteWithSetArgument()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -326,7 +326,7 @@ public function testInvokeWithMatchingRouteWithSetArguments()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -354,7 +354,7 @@ public function testInvokeWithMatchingRouteWithNamedParameter()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -387,7 +387,7 @@ public function testInvokeWithMatchingRouteWithNamedParameterRequestResponseArgS
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -415,7 +415,7 @@ public function testInvokeWithMatchingRouteWithNamedParameterOverwritesSetArgume
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -445,7 +445,7 @@ public function testInvokeWithoutMatchingRoute()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand All @@ -468,7 +468,7 @@ public function testInvokeWithPimpleCallable()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -505,7 +505,7 @@ public function testInvokeWithPimpleUndefinedCallable()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -537,7 +537,7 @@ public function testInvokeWithPimpleCallableViaMagicMethod()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down Expand Up @@ -578,7 +578,7 @@ function handle($req, $res) {
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand All @@ -605,7 +605,7 @@ public function testCurrentRequestAttributesAreNotLostWhenAddingRouteArguments()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$req = $req->withAttribute("one", 1);
$res = new Response();
Expand Down Expand Up @@ -638,7 +638,7 @@ public function testCurrentRequestAttributesAreNotLostWhenAddingRouteArgumentsRe
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$req = $req->withAttribute("one", 1);
$res = new Response();
Expand Down Expand Up @@ -717,7 +717,7 @@ public function testRespond()
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body = new RequestBody();
$req = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();

Expand Down

0 comments on commit 39d12e5

Please sign in to comment.