Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
"php": ">=7.1",
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
"fig/http-message-util": "^1.1",
"psr/http-message": "^1.0",
"psr/http-message": "^2.0 || ^1.0",
"react/event-loop": "^1.2",
"react/promise": "^3.2 || ^2.3 || ^1.2.1",
"react/socket": "^1.16",
"react/stream": "^1.4"
},
"require-dev": {
"clue/http-proxy-react": "^1.8",
"clue/http-proxy-react": "^1.10",
"clue/reactphp-ssh-proxy": "^1.4",
"clue/socks-react": "^1.4",
"phpunit/phpunit": "^9.6 || ^8.5 || ^7.5",
Expand All @@ -47,7 +47,10 @@
"autoload": {
"psr-4": {
"React\\Http\\": "src/"
}
},
"exclude-from-classmap": [
"src/**.v1.php"
]
},
"autoload-dev": {
"psr-4": {
Expand Down
32 changes: 20 additions & 12 deletions src/Io/AbstractMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\StreamInterface;

if (!(new \ReflectionParameter([MessageInterface::class, 'withProtocolVersion'], 0))->hasType()) {
// load legacy class for psr/http-message v1.0 without native parameter types
require __DIR__ . '/AbstractMessage.v1.php';
} else {
// use class with native types like `withProtocolVersion(string $version): MessageInterface`

/**
* [Internal] Abstract HTTP message base class (PSR-7)
* [Internal] Abstract HTTP message base class (PSR-7 v2)
*
* @internal
* @see MessageInterface
* @see AbstractMessage.v1.php (PSR-7 v1)
*/
abstract class AbstractMessage implements MessageInterface
{
Expand Down Expand Up @@ -65,12 +72,12 @@ protected function __construct($protocolVersion, array $headers, StreamInterface
$this->body = $body;
}

public function getProtocolVersion()
public function getProtocolVersion(): string
{
return $this->protocolVersion;
}

public function withProtocolVersion($version)
public function withProtocolVersion(string $version): MessageInterface
{
if ((string) $version === $this->protocolVersion) {
return $this;
Expand All @@ -82,28 +89,28 @@ public function withProtocolVersion($version)
return $message;
}

public function getHeaders()
public function getHeaders(): array
{
return $this->headers;
}

public function hasHeader($name)
public function hasHeader(string $name): bool
{
return isset($this->headerNamesLowerCase[\strtolower($name)]);
}

public function getHeader($name)
public function getHeader(string $name): array
{
$lower = \strtolower($name);
return isset($this->headerNamesLowerCase[$lower]) ? $this->headers[$this->headerNamesLowerCase[$lower]] : [];
}

public function getHeaderLine($name)
public function getHeaderLine(string $name): string
{
return \implode(', ', $this->getHeader($name));
}

public function withHeader($name, $value)
public function withHeader(string $name, $value): MessageInterface
{
if ($value === []) {
return $this->withoutHeader($name);
Expand Down Expand Up @@ -131,7 +138,7 @@ public function withHeader($name, $value)
return $message;
}

public function withAddedHeader($name, $value)
public function withAddedHeader(string $name, $value): MessageInterface
{
if ($value === []) {
return $this;
Expand All @@ -140,7 +147,7 @@ public function withAddedHeader($name, $value)
return $this->withHeader($name, \array_merge($this->getHeader($name), \is_array($value) ? $value : [$value]));
}

public function withoutHeader($name)
public function withoutHeader(string $name): MessageInterface
{
$lower = \strtolower($name);
if (!isset($this->headerNamesLowerCase[$lower])) {
Expand All @@ -153,12 +160,12 @@ public function withoutHeader($name)
return $message;
}

public function getBody()
public function getBody(): StreamInterface
{
return $this->body;
}

public function withBody(StreamInterface $body)
public function withBody(StreamInterface $body): MessageInterface
{
if ($body === $this->body) {
return $this;
Expand All @@ -170,3 +177,4 @@ public function withBody(StreamInterface $body)
return $message;
}
}
}
173 changes: 173 additions & 0 deletions src/Io/AbstractMessage.v1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php

namespace React\Http\Io;

use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\StreamInterface;

/**
* [Internal] Abstract HTTP message base class (PSR-7 v1)
*
* @internal
* @see MessageInterface
* @see AbstractMessage.php (PSR-7 v2)
*/
abstract class AbstractMessage implements MessageInterface
{
/**
* [Internal] Regex used to match all request header fields into an array, thanks to @kelunik for checking the HTTP specs and coming up with this regex
*
* @internal
* @var string
*/
const REGEX_HEADERS = '/^([^()<>@,;:\\\"\/\[\]?={}\x00-\x20\x7F]++):[\x20\x09]*+((?:[\x20\x09]*+[\x21-\x7E\x80-\xFF]++)*+)[\x20\x09]*+[\r]?+\n/m';

/** @var array<string,string[]> */
private $headers = [];

/** @var array<string,string> */
private $headerNamesLowerCase = [];

/** @var string */
private $protocolVersion;

/** @var StreamInterface */
private $body;

/**
* @param string $protocolVersion
* @param array<string,string|string[]> $headers
* @param StreamInterface $body
*/
protected function __construct($protocolVersion, array $headers, StreamInterface $body)
{
foreach ($headers as $name => $value) {
if ($value !== []) {
if (\is_array($value)) {
foreach ($value as &$one) {
$one = (string) $one;
}
} else {
$value = [(string) $value];
}

$lower = \strtolower($name);
if (isset($this->headerNamesLowerCase[$lower])) {
$value = \array_merge($this->headers[$this->headerNamesLowerCase[$lower]], $value);
unset($this->headers[$this->headerNamesLowerCase[$lower]]);
}

$this->headers[$name] = $value;
$this->headerNamesLowerCase[$lower] = $name;
}
}

$this->protocolVersion = (string) $protocolVersion;
$this->body = $body;
}

public function getProtocolVersion(): string
{
return $this->protocolVersion;
}

public function withProtocolVersion($version): MessageInterface
{
if ((string) $version === $this->protocolVersion) {
return $this;
}

$message = clone $this;
$message->protocolVersion = (string) $version;

return $message;
}

public function getHeaders(): array
{
return $this->headers;
}

public function hasHeader($name): bool
{
return isset($this->headerNamesLowerCase[\strtolower($name)]);
}

public function getHeader($name): array
{
$lower = \strtolower($name);
return isset($this->headerNamesLowerCase[$lower]) ? $this->headers[$this->headerNamesLowerCase[$lower]] : [];
}

public function getHeaderLine($name): string
{
return \implode(', ', $this->getHeader($name));
}

public function withHeader($name, $value): MessageInterface
{
if ($value === []) {
return $this->withoutHeader($name);
} elseif (\is_array($value)) {
foreach ($value as &$one) {
$one = (string) $one;
}
} else {
$value = [(string) $value];
}

$lower = \strtolower($name);
if (isset($this->headerNamesLowerCase[$lower]) && $this->headerNamesLowerCase[$lower] === (string) $name && $this->headers[$this->headerNamesLowerCase[$lower]] === $value) {
return $this;
}

$message = clone $this;
if (isset($message->headerNamesLowerCase[$lower])) {
unset($message->headers[$message->headerNamesLowerCase[$lower]]);
}

$message->headers[$name] = $value;
$message->headerNamesLowerCase[$lower] = $name;

return $message;
}

public function withAddedHeader($name, $value): MessageInterface
{
if ($value === []) {
return $this;
}

return $this->withHeader($name, \array_merge($this->getHeader($name), \is_array($value) ? $value : [$value]));
}

public function withoutHeader($name): MessageInterface
{
$lower = \strtolower($name);
if (!isset($this->headerNamesLowerCase[$lower])) {
return $this;
}

$message = clone $this;
unset($message->headers[$message->headerNamesLowerCase[$lower]], $message->headerNamesLowerCase[$lower]);

return $message;
}

public function getBody(): StreamInterface
{
return $this->body;
}

public function withBody(StreamInterface $body): MessageInterface
{
if ($body === $this->body) {
return $this;
}

$message = clone $this;
$message->body = $body;

return $message;
}
}
22 changes: 15 additions & 7 deletions src/Io/AbstractRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@
use Psr\Http\Message\UriInterface;
use React\Http\Message\Uri;

if (!(new \ReflectionParameter([RequestInterface::class, 'withMethod'], 0))->hasType()) {
// load legacy class for psr/http-message v1.0 without native parameter types
require __DIR__ . '/AbstractRequest.v1.php';
} else {
// use class with native types like `withMethod(string $method): RequestInterface`

/**
* [Internal] Abstract HTTP request base class (PSR-7)
* [Internal] Abstract HTTP request base class (PSR-7 v2)
*
* @internal
* @see RequestInterface
* @see AbstractRequest.v1.php (PSR-7 v1)
*/
abstract class AbstractRequest extends AbstractMessage implements RequestInterface
{
Expand Down Expand Up @@ -71,7 +78,7 @@ protected function __construct(
$this->uri = $uri;
}

public function getRequestTarget()
public function getRequestTarget(): string
{
if ($this->requestTarget !== null) {
return $this->requestTarget;
Expand All @@ -88,7 +95,7 @@ public function getRequestTarget()
return $target;
}

public function withRequestTarget($requestTarget)
public function withRequestTarget(string $requestTarget): RequestInterface
{
if ((string) $requestTarget === $this->requestTarget) {
return $this;
Expand All @@ -100,12 +107,12 @@ public function withRequestTarget($requestTarget)
return $request;
}

public function getMethod()
public function getMethod(): string
{
return $this->method;
}

public function withMethod($method)
public function withMethod(string $method): RequestInterface
{
if ((string) $method === $this->method) {
return $this;
Expand All @@ -117,12 +124,12 @@ public function withMethod($method)
return $request;
}

public function getUri()
public function getUri(): UriInterface
{
return $this->uri;
}

public function withUri(UriInterface $uri, $preserveHost = false)
public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface
{
if ($uri === $this->uri) {
return $this;
Expand Down Expand Up @@ -154,3 +161,4 @@ public function withUri(UriInterface $uri, $preserveHost = false)
return $request;
}
}
}
Loading
Loading