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
11 changes: 7 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,28 @@
"php": ">=5.3.0",
"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 || ^5.7 || ^4.8.36",
"phpunit/phpunit": "^9.6 || ^8.5 || ^5.7 || ^4.8.36",
"react/async": "^4.2 || ^3 || ^2",
"react/promise-stream": "^1.4",
"react/promise-timer": "^1.11"
},
"autoload": {
"psr-4": {
"React\\Http\\": "src/"
}
},
"exclude-from-classmap": [
"src/**.v2.php"
]
},
"autoload-dev": {
"psr-4": {
Expand Down
11 changes: 10 additions & 1 deletion src/Io/AbstractMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\StreamInterface;


if (\PHP_VERSION_ID >= 70000 && \call_user_func(array(new \ReflectionMethod('\Psr\Http\Message\MessageInterface', 'getProtocolVersion'), 'hasReturnType'))) {
// load class for psr/http-message v2 using native types like `getProtocolVersion(): string`
require __DIR__ . '/AbstractMessage.v2.php';
} else {
// fall back to class without native types

/**
* [Internal] Abstract HTTP message base class (PSR-7)
* [Internal] Abstract HTTP message base class (PSR-7 v1)
*
* @internal
* @see MessageInterface
* @see AbstractMessage.v2.php (PSR-7 v2)
*/
abstract class AbstractMessage implements MessageInterface
{
Expand Down Expand Up @@ -170,3 +178,4 @@ public function withBody(StreamInterface $body)
return $message;
}
}
}
173 changes: 173 additions & 0 deletions src/Io/AbstractMessage.v2.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 v2)
*
* @internal
* @see MessageInterface
* @see AbstractMessage.php (PSR-7 v1)
*/
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 = array();

/** @var array<string,string> */
private $headerNamesLowerCase = array();

/** @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 !== array()) {
if (\is_array($value)) {
foreach ($value as &$one) {
$one = (string) $one;
}
} else {
$value = array((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(string $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(string $name): bool
{
return isset($this->headerNamesLowerCase[\strtolower($name)]);
}

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

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

public function withHeader(string $name, $value): MessageInterface
{
if ($value === array()) {
return $this->withoutHeader($name);
} elseif (\is_array($value)) {
foreach ($value as &$one) {
$one = (string) $one;
}
} else {
$value = array((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(string $name, $value): MessageInterface
{
if ($value === array()) {
return $this;
}

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

public function withoutHeader(string $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;
}
}
10 changes: 9 additions & 1 deletion 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 (\PHP_VERSION_ID >= 70000 && \call_user_func(array(new \ReflectionMethod('\Psr\Http\Message\RequestInterface', 'getRequestTarget'), 'hasReturnType'))) {
// load class for psr/http-message v2 using native types like `getRequestTarget(): string`
require __DIR__ . '/AbstractRequest.v2.php';
} else {
// fall back to class without native types

/**
* [Internal] Abstract HTTP request base class (PSR-7)
* [Internal] Abstract HTTP request base class (PSR-7 v1)
*
* @internal
* @see RequestInterface
* @see AbstractRequest.v2.php (PSR-7 v2)
*/
abstract class AbstractRequest extends AbstractMessage implements RequestInterface
{
Expand Down Expand Up @@ -154,3 +161,4 @@ public function withUri(UriInterface $uri, $preserveHost = false)
return $request;
}
}
}
Loading
Loading