Refactor ServerRequestMarshaller and ServerRequest
This commit is contained in:
parent
20012dc671
commit
9243dd7663
|
|
@ -4,7 +4,9 @@ namespace WellRESTed\Message;
|
|||
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Representation of an incoming, server-side HTTP request.
|
||||
|
|
@ -51,9 +53,31 @@ class ServerRequest extends Request implements ServerRequestInterface
|
|||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function __construct(array $serverParams = [])
|
||||
{
|
||||
parent::__construct();
|
||||
/**
|
||||
* Create a new ServerRequest.
|
||||
*
|
||||
* $headers is an optional associative array with header field names as
|
||||
* string keys and values as either string or string[].
|
||||
*
|
||||
* If no StreamInterface is provided for $body, the instance will create
|
||||
* a NullStream instance for the message body.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string|UriInterface $uri
|
||||
* @param array $headers Associative array with header field names as
|
||||
* keys and values as string|string[]
|
||||
* @param StreamInterface|null $body A stream representation of the message
|
||||
* entity body
|
||||
* @param array $serverParams An array of Server API (SAPI) parameters
|
||||
*/
|
||||
public function __construct(
|
||||
string $method = 'GET',
|
||||
$uri = '',
|
||||
array $headers = [],
|
||||
?StreamInterface $body = null,
|
||||
array $serverParams = []
|
||||
){
|
||||
parent::__construct($method, $uri, $headers, $body);
|
||||
$this->serverParams = $serverParams;
|
||||
$this->cookieParams = [];
|
||||
$this->queryParams = [];
|
||||
|
|
|
|||
|
|
@ -8,38 +8,28 @@ use Psr\Http\Message\UriInterface;
|
|||
|
||||
class ServerRequestMarshaller
|
||||
{
|
||||
public function getServerRequest(
|
||||
?array $serverParams = null,
|
||||
?array $cookieParams = null,
|
||||
?array $queryParams = null,
|
||||
?array $postParams = null,
|
||||
?array $fileParams = null,
|
||||
string $inputStream = 'php://input'
|
||||
): ServerRequestInterface {
|
||||
$serverParams = $serverParams ?? $_SERVER;
|
||||
$cookieParams = $cookieParams ?? $_COOKIE;
|
||||
$queryParams = $queryParams ?? self::parseQuery($serverParams);
|
||||
$postParams = $postParams ?? $_POST;
|
||||
$fileParams = $fileParams ?? $_FILES;
|
||||
/**
|
||||
* Read the request as sent from the client and construct a ServerRequest
|
||||
* representation.
|
||||
*
|
||||
* @return ServerRequestInterface
|
||||
* @internal
|
||||
*/
|
||||
public function getServerRequest(): ServerRequestInterface
|
||||
{
|
||||
$method = self::parseMethod($_SERVER);
|
||||
$uri = self::readUri($_SERVER);
|
||||
$headers = self::parseHeaders($_SERVER);
|
||||
$body = self::readBody();
|
||||
|
||||
$request = new ServerRequest($serverParams);
|
||||
|
||||
$request = $request
|
||||
->withProtocolVersion(self::parseProtocolVersion($serverParams))
|
||||
->withMethod(self::parseMethod($serverParams))
|
||||
->withBody(self::readBody($inputStream))
|
||||
->withUri(self::readUri($serverParams))
|
||||
->withUploadedFiles(self::readUploadedFiles($fileParams))
|
||||
->withCookieParams($cookieParams)
|
||||
->withQueryParams($queryParams);
|
||||
|
||||
$headers = self::parseHeaders($serverParams);
|
||||
foreach ($headers as $name => $value) {
|
||||
$request = $request->withAddedHeader($name, $value);
|
||||
}
|
||||
$request = (new ServerRequest($method, $uri, $headers, $body, $_SERVER))
|
||||
->withProtocolVersion(self::parseProtocolVersion($_SERVER))
|
||||
->withUploadedFiles(self::readUploadedFiles($_FILES))
|
||||
->withCookieParams($_COOKIE)
|
||||
->withQueryParams(self::parseQuery($_SERVER));
|
||||
|
||||
if (self::isForm($request)) {
|
||||
$request = $request->withParsedBody($postParams);
|
||||
$request = $request->withParsedBody($_POST);
|
||||
}
|
||||
|
||||
return $request;
|
||||
|
|
@ -95,9 +85,9 @@ class ServerRequestMarshaller
|
|||
return $serverParams['REQUEST_METHOD'] ?? 'GET';
|
||||
}
|
||||
|
||||
private static function readBody(string $inputStream): StreamInterface
|
||||
private static function readBody(): StreamInterface
|
||||
{
|
||||
$input = fopen($inputStream, 'rb');
|
||||
$input = fopen('php://input', 'rb');
|
||||
$temp = fopen('php://temp', 'wb+');
|
||||
stream_copy_to_stream($input, $temp);
|
||||
rewind($temp);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class ServerRequestMarshallerTest extends TestCase
|
|||
'hamster' => 'Dusty'
|
||||
];
|
||||
|
||||
FopenHelper::$inputTempFile = null;
|
||||
|
||||
$this->marshaller = new ServerRequestMarshaller();
|
||||
}
|
||||
|
||||
|
|
@ -103,15 +105,9 @@ class ServerRequestMarshallerTest extends TestCase
|
|||
$tempFilePath = tempnam(sys_get_temp_dir(), 'test');
|
||||
$content = 'Body content';
|
||||
file_put_contents($tempFilePath, $content);
|
||||
FopenHelper::$inputTempFile = $tempFilePath;
|
||||
|
||||
$request = $this->marshaller->getServerRequest(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$tempFilePath
|
||||
);
|
||||
$request = $this->marshaller->getServerRequest();
|
||||
unlink($tempFilePath);
|
||||
|
||||
$this->assertEquals($content, (string) $request->getBody());
|
||||
|
|
@ -182,7 +178,8 @@ class ServerRequestMarshallerTest extends TestCase
|
|||
*/
|
||||
public function testProvidesUri(UriInterface $expected, array $serverParams): void
|
||||
{
|
||||
$request = $this->marshaller->getServerRequest($serverParams);
|
||||
$_SERVER = $serverParams;
|
||||
$request = $this->marshaller->getServerRequest();
|
||||
$this->assertEquals($expected, $request->getUri());
|
||||
}
|
||||
|
||||
|
|
@ -379,3 +376,25 @@ class ServerRequestMarshallerTest extends TestCase
|
|||
];
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Declare fopen function in this namespace so the class under test will use
|
||||
// this instead of the internal global functions during testing.
|
||||
|
||||
class FopenHelper
|
||||
{
|
||||
/**
|
||||
* @var string Path to temp file to read in place of 'php://input'
|
||||
*/
|
||||
public static $inputTempFile;
|
||||
}
|
||||
|
||||
function fopen($filename, $mode)
|
||||
{
|
||||
if (FopenHelper::$inputTempFile && $filename === 'php://input') {
|
||||
$filename = FopenHelper::$inputTempFile;
|
||||
}
|
||||
|
||||
return \fopen($filename, $mode);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue