Change Request constructor signature
Various updates to Message classes
This commit is contained in:
parent
bdc5ac40d9
commit
7ade042b4b
12
psalm.xml
12
psalm.xml
|
|
@ -13,4 +13,16 @@
|
||||||
<directory name="vendor" />
|
<directory name="vendor" />
|
||||||
</ignoreFiles>
|
</ignoreFiles>
|
||||||
</projectFiles>
|
</projectFiles>
|
||||||
|
<issueHandlers>
|
||||||
|
<DocblockTypeContradiction>
|
||||||
|
<errorLevel type="suppress">
|
||||||
|
<file name="src/Message/ServerRequest.php" />
|
||||||
|
</errorLevel>
|
||||||
|
</DocblockTypeContradiction>
|
||||||
|
<MissingClosureParamType>
|
||||||
|
<errorLevel type="suppress">
|
||||||
|
<file name="src/Message/Message.php" />
|
||||||
|
</errorLevel>
|
||||||
|
</MissingClosureParamType>
|
||||||
|
</issueHandlers>
|
||||||
</psalm>
|
</psalm>
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,13 @@ abstract class Message implements MessageInterface
|
||||||
*
|
*
|
||||||
* @param array $headers Associative array with header field names as
|
* @param array $headers Associative array with header field names as
|
||||||
* (string) keys and lists of header field values (string[]) as values.
|
* (string) keys and lists of header field values (string[]) as values.
|
||||||
* @param StreamInterface $body A stream representation of the message
|
* @param StreamInterface|null $body A stream representation of the message
|
||||||
* entity body
|
* entity body
|
||||||
*/
|
*/
|
||||||
public function __construct(array $headers = null, StreamInterface $body = null)
|
public function __construct(
|
||||||
{
|
array $headers = [],
|
||||||
|
?StreamInterface $body = null
|
||||||
|
) {
|
||||||
$this->headers = new HeaderCollection();
|
$this->headers = new HeaderCollection();
|
||||||
if ($headers) {
|
if ($headers) {
|
||||||
foreach ($headers as $name => $values) {
|
foreach ($headers as $name => $values) {
|
||||||
|
|
@ -265,22 +267,32 @@ abstract class Message implements MessageInterface
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
private function getValidatedHeaders($name, $value)
|
/**
|
||||||
|
* @param mixed $name
|
||||||
|
* @param mixed|mixed[] $values
|
||||||
|
* @return string[]
|
||||||
|
* @throws \InvalidArgumentException Name is not a string or value is not
|
||||||
|
* a string or array of strings
|
||||||
|
*/
|
||||||
|
private function getValidatedHeaders($name, $values)
|
||||||
{
|
{
|
||||||
$is_allowed = function ($item) {
|
|
||||||
return is_string($item) || is_numeric($item);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!is_string($name)) {
|
if (!is_string($name)) {
|
||||||
throw new \InvalidArgumentException('Header name must be a string');
|
throw new \InvalidArgumentException('Header name must be a string');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($is_allowed($value)) {
|
if (!is_array($values)) {
|
||||||
return [$value];
|
$values = [$values];
|
||||||
} elseif (is_array($value) && count($value) === count(array_filter($value, $is_allowed))) {
|
}
|
||||||
return $value;
|
|
||||||
} else {
|
$isNotStringOrNumber = function ($item): bool {
|
||||||
|
return !(is_string($item) || is_numeric($item));
|
||||||
|
};
|
||||||
|
|
||||||
|
$invalid = array_filter($values, $isNotStringOrNumber);
|
||||||
|
if ($invalid) {
|
||||||
throw new \InvalidArgumentException('Header values must be a string or string[]');
|
throw new \InvalidArgumentException('Header values must be a string or string[]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return array_map('strval', $values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ class NullStream implements StreamInterface
|
||||||
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
|
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
|
||||||
* offset bytes SEEK_CUR: Set position to current location plus offset
|
* offset bytes SEEK_CUR: Set position to current location plus offset
|
||||||
* SEEK_END: Set position to end-of-stream plus offset.
|
* SEEK_END: Set position to end-of-stream plus offset.
|
||||||
|
* @return void
|
||||||
* @throws \RuntimeException on failure.
|
* @throws \RuntimeException on failure.
|
||||||
*/
|
*/
|
||||||
public function seek($offset, $whence = SEEK_SET)
|
public function seek($offset, $whence = SEEK_SET)
|
||||||
|
|
@ -103,6 +104,7 @@ class NullStream implements StreamInterface
|
||||||
*
|
*
|
||||||
* @see seek()
|
* @see seek()
|
||||||
* @link http://www.php.net/manual/en/function.fseek.php
|
* @link http://www.php.net/manual/en/function.fseek.php
|
||||||
|
* @return void
|
||||||
* @throws \RuntimeException on failure.
|
* @throws \RuntimeException on failure.
|
||||||
*/
|
*/
|
||||||
public function rewind()
|
public function rewind()
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class Request extends Message implements RequestInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $method;
|
protected $method;
|
||||||
/** @var string */
|
/** @var string|null */
|
||||||
protected $requestTarget;
|
protected $requestTarget;
|
||||||
/** @var UriInterface */
|
/** @var UriInterface */
|
||||||
protected $uri;
|
protected $uri;
|
||||||
|
|
@ -33,26 +33,24 @@ class Request extends Message implements RequestInterface
|
||||||
* Create a new Request.
|
* Create a new Request.
|
||||||
*
|
*
|
||||||
* @see \WellRESTed\Message\Message
|
* @see \WellRESTed\Message\Message
|
||||||
* @param UriInterface $uri
|
* @param string|UriInterface $uri
|
||||||
* @param string $method
|
* @param string $method
|
||||||
* @param array $headers
|
* @param array $headers
|
||||||
* @param StreamInterface $body
|
* @param StreamInterface|null $body
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
UriInterface $uri = null,
|
string $method = 'GET',
|
||||||
$method = "GET",
|
$uri = '',
|
||||||
array $headers = null,
|
array $headers = [],
|
||||||
StreamInterface $body = null
|
?StreamInterface $body = null
|
||||||
) {
|
) {
|
||||||
parent::__construct($headers, $body);
|
parent::__construct($headers, $body);
|
||||||
|
|
||||||
if ($uri !== null) {
|
|
||||||
$this->uri = $uri;
|
|
||||||
} else {
|
|
||||||
$this->uri = new Uri();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->method = $method;
|
$this->method = $method;
|
||||||
|
if (!($uri instanceof UriInterface)) {
|
||||||
|
$uri = new Uri($uri);
|
||||||
|
}
|
||||||
|
$this->uri = $uri;
|
||||||
|
$this->requestTarget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __clone()
|
public function __clone()
|
||||||
|
|
@ -83,7 +81,7 @@ class Request extends Message implements RequestInterface
|
||||||
public function getRequestTarget()
|
public function getRequestTarget()
|
||||||
{
|
{
|
||||||
// Use the explicitly set request target first.
|
// Use the explicitly set request target first.
|
||||||
if (isset($this->requestTarget)) {
|
if ($this->requestTarget !== null) {
|
||||||
return $this->requestTarget;
|
return $this->requestTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,7 +209,7 @@ class Request extends Message implements RequestInterface
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $method
|
* @param mixed $method
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,13 @@ class Response extends Message implements ResponseInterface
|
||||||
* @see \WellRESTed\Message\Message
|
* @see \WellRESTed\Message\Message
|
||||||
* @param int $statusCode
|
* @param int $statusCode
|
||||||
* @param array $headers
|
* @param array $headers
|
||||||
* @param StreamInterface $body
|
* @param StreamInterface|null $body
|
||||||
*/
|
*/
|
||||||
public function __construct($statusCode = 500, array $headers = null, StreamInterface $body = null)
|
public function __construct(
|
||||||
{
|
int $statusCode = 500,
|
||||||
|
array $headers = [],
|
||||||
|
?StreamInterface $body = null
|
||||||
|
) {
|
||||||
parent::__construct($headers, $body);
|
parent::__construct($headers, $body);
|
||||||
$this->statusCode = $statusCode;
|
$this->statusCode = $statusCode;
|
||||||
$this->reasonPhrase = $this->getDefaultReasonPhraseForStatusCode($statusCode);
|
$this->reasonPhrase = $this->getDefaultReasonPhraseForStatusCode($statusCode);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace WellRESTed\Message;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\StreamInterface;
|
use Psr\Http\Message\StreamInterface;
|
||||||
use Psr\Http\Message\UploadedFileInterface;
|
use Psr\Http\Message\UploadedFileInterface;
|
||||||
|
use Psr\Http\Message\UriInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of an incoming, server-side HTTP request.
|
* Representation of an incoming, server-side HTTP request.
|
||||||
|
|
@ -336,9 +337,13 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
protected function readFromServerRequest(array $attributes = null)
|
/**
|
||||||
|
* @param array $attributes
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function readFromServerRequest(array $attributes = [])
|
||||||
{
|
{
|
||||||
$this->attributes = $attributes ?: [];
|
$this->attributes = $attributes;
|
||||||
$this->serverParams = $_SERVER;
|
$this->serverParams = $_SERVER;
|
||||||
$this->cookieParams = $_COOKIE;
|
$this->cookieParams = $_COOKIE;
|
||||||
$this->readUploadedFiles($_FILES);
|
$this->readUploadedFiles($_FILES);
|
||||||
|
|
@ -367,7 +372,7 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function readUploadedFiles($input)
|
protected function readUploadedFiles(array $input): void
|
||||||
{
|
{
|
||||||
$uploadedFiles = [];
|
$uploadedFiles = [];
|
||||||
foreach ($input as $name => $value) {
|
foreach ($input as $name => $value) {
|
||||||
|
|
@ -376,8 +381,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
$this->uploadedFiles = $uploadedFiles;
|
$this->uploadedFiles = $uploadedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function addUploadedFilesToBranch(&$branch, $name, $value)
|
protected function addUploadedFilesToBranch(
|
||||||
{
|
array &$branch,
|
||||||
|
string $name,
|
||||||
|
array $value
|
||||||
|
): void {
|
||||||
// Check for each of the expected keys.
|
// Check for each of the expected keys.
|
||||||
if (isset($value["name"], $value["type"], $value["tmp_name"], $value["error"], $value["size"])) {
|
if (isset($value["name"], $value["type"], $value["tmp_name"], $value["error"], $value["size"])) {
|
||||||
// This is a file. It may be a single file, or a list of files.
|
// This is a file. It may be a single file, or a list of files.
|
||||||
|
|
@ -419,7 +427,7 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function readUri()
|
protected function readUri(): UriInterface
|
||||||
{
|
{
|
||||||
$uri = "";
|
$uri = "";
|
||||||
|
|
||||||
|
|
@ -449,7 +457,7 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
* @return static
|
* @return static
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
public static function getServerRequest(array $attributes = null)
|
public static function getServerRequest(array $attributes = [])
|
||||||
{
|
{
|
||||||
$request = new static();
|
$request = new static();
|
||||||
$request->readFromServerRequest($attributes);
|
$request->readFromServerRequest($attributes);
|
||||||
|
|
@ -480,28 +488,22 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
protected function getServerRequestHeaders()
|
protected function getServerRequestHeaders()
|
||||||
{
|
{
|
||||||
// http://www.php.net/manual/en/function.getallheaders.php#84262
|
// http://www.php.net/manual/en/function.getallheaders.php#84262
|
||||||
$headers = array();
|
$headers = [];
|
||||||
foreach ($_SERVER as $name => $value) {
|
foreach ($_SERVER as $name => $value) {
|
||||||
if (substr($name, 0, 5) === "HTTP_") {
|
if (substr($name, 0, 5) === "HTTP_") {
|
||||||
$name = $this->normalizeHeaderName(substr($name, 5));
|
$name = $this->normalizeHeaderName(substr($name, 5));
|
||||||
$headers[$name] = $value;
|
$headers[$name] = trim($value);
|
||||||
} elseif ($this->isContentHeader($name, $value)) {
|
} elseif ($this->isContentHeader($name) && !empty(trim($value))) {
|
||||||
$name = $this->normalizeHeaderName($name);
|
$name = $this->normalizeHeaderName($name);
|
||||||
$headers[$name] = $value;
|
$headers[$name] = trim($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $headers;
|
return $headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function isContentHeader(string $name): bool
|
||||||
* @param $name
|
|
||||||
* @param $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isContentHeader($name, $value)
|
|
||||||
{
|
{
|
||||||
return ($name === "CONTENT_LENGTH" || $name === "CONTENT_TYPE")
|
return ($name === 'CONTENT_LENGTH' || $name === 'CONTENT_TYPE');
|
||||||
&& trim($value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -540,7 +542,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isValidUploadedFilesBranch($branch)
|
/**
|
||||||
|
* @param UploadedFileInterface|array $branch
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isValidUploadedFilesBranch($branch): bool
|
||||||
{
|
{
|
||||||
if (is_array($branch)) {
|
if (is_array($branch)) {
|
||||||
// Branch.
|
// Branch.
|
||||||
|
|
|
||||||
|
|
@ -19,32 +19,39 @@ class RequestTest extends TestCase
|
||||||
$this->assertNotNull($request);
|
$this->assertNotNull($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCreatesInstanceWithMethod()
|
||||||
|
{
|
||||||
|
$method = 'POST';
|
||||||
|
$request = new Request($method);
|
||||||
|
$this->assertSame($method, $request->getMethod());
|
||||||
|
}
|
||||||
|
|
||||||
public function testCreatesInstanceWithUri()
|
public function testCreatesInstanceWithUri()
|
||||||
{
|
{
|
||||||
$uri = new Uri();
|
$uri = new Uri();
|
||||||
$request = new Request($uri);
|
$request = new Request('GET', $uri);
|
||||||
$this->assertSame($uri, $request->getUri());
|
$this->assertSame($uri, $request->getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreatesInstanceWithMethod()
|
public function testCreatesInstanceWithStringUri()
|
||||||
{
|
{
|
||||||
$method = "POST";
|
$uri = 'http://localhost:8080';
|
||||||
$request = new Request(null, $method);
|
$request = new Request('GET', $uri);
|
||||||
$this->assertSame($method, $request->getMethod());
|
$this->assertSame($uri, (string) $request->getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetsHeadersOnConstruction()
|
public function testSetsHeadersOnConstruction()
|
||||||
{
|
{
|
||||||
$request = new Request(null, null, [
|
$request = new Request('GET', '/', [
|
||||||
"X-foo" => ["bar","baz"]
|
'X-foo' => ['bar', 'baz']
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(["bar","baz"], $request->getHeader("X-foo"));
|
$this->assertEquals(['bar', 'baz'], $request->getHeader('X-foo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetsBodyOnConstruction()
|
public function testSetsBodyOnConstruction()
|
||||||
{
|
{
|
||||||
$body = new NullStream();
|
$body = new NullStream();
|
||||||
$request = new Request(null, null, [], $body);
|
$request = new Request('GET', '/', [], $body);
|
||||||
$this->assertSame($body, $request->getBody());
|
$this->assertSame($body, $request->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue