diff --git a/README.md b/README.md index 891c9f7e..f95214e5 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ multiple concurrent HTTP requests without blocking. * [Request method](#request-method) * [Cookie parameters](#cookie-parameters) * [Invalid request](#invalid-request) - * [Response](#response) + * [Server Response](#server-response) * [Deferred response](#deferred-response) * [Streaming outgoing response](#streaming-outgoing-response) * [Response length](#response-length) @@ -68,6 +68,9 @@ multiple concurrent HTTP requests without blocking. * [withBase()](#withbase) * [withProtocolVersion()](#withprotocolversion) * [withResponseBuffer()](#withresponsebuffer) + * [React\Http\Message](#reacthttpmessage) + * [Response](#response) + * [ServerRequest](#serverrequest) * [React\Http\Middleware](#reacthttpmiddleware) * [StreamingRequestMiddleware](#streamingrequestmiddleware) * [LimitConcurrentRequestsMiddleware](#limitconcurrentrequestsmiddleware) @@ -102,7 +105,7 @@ This is an HTTP server which responds with `Hello World!` to every request. $loop = React\EventLoop\Factory::create(); $server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { - return new React\Http\Response( + return new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -711,11 +714,11 @@ processing each incoming HTTP request. When a complete HTTP request has been received, it will invoke the given request handler function. This request handler function needs to be passed to the constructor and will be invoked with the respective [request](#server-request) -object and expects a [response](#response) object in return: +object and expects a [response](#server-response) object in return: ```php $server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { - return new React\Http\Response( + return new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -731,7 +734,7 @@ see also following [request](#server-request) chapter for more details. Each outgoing HTTP response message is always represented by the [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), -see also following [response](#response) chapter for more details. +see also following [response](#server-response) chapter for more details. In order to start listening for any incoming connections, the `Server` needs to be attached to an instance of @@ -1158,7 +1161,7 @@ $server = new React\Http\Server( }); $body->on('end', function () use ($resolve, &$bytes){ - $resolve(new React\Http\Response( + $resolve(new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -1169,7 +1172,7 @@ $server = new React\Http\Server( // an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event $body->on('error', function (\Exception $exception) use ($resolve, &$bytes) { - $resolve(new React\Http\Response( + $resolve(new React\Http\Message\Response( 400, array( 'Content-Type' => 'text/plain' @@ -1226,7 +1229,7 @@ $server = new React\Http\Server( $body = 'The request does not contain an explicit length.'; $body .= 'This example does not accept chunked transfer encoding.'; - return new React\Http\Response( + return new React\Http\Message\Response( 411, array( 'Content-Type' => 'text/plain' @@ -1235,7 +1238,7 @@ $server = new React\Http\Server( ); } - return new React\Http\Response( + return new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -1346,25 +1349,24 @@ Note that the server will also emit an `error` event if you do not return a valid response object from your request handler function. See also [invalid response](#invalid-response) for more details. -### Response +### Server Response The callback function passed to the constructor of the [`Server`](#server) is responsible for processing the request and returning a response, which will be -delivered to the client. This function MUST return an instance implementing -[PSR-7 ResponseInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#33-psrhttpmessageresponseinterface) +delivered to the client. + +This function MUST return an instance implementing +[PSR-7 `ResponseInterface`](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#33-psrhttpmessageresponseinterface) object or a -[ReactPHP Promise](https://github.com/reactphp/promise#reactpromise) -which will resolve a `PSR-7 ResponseInterface` object. +[ReactPHP Promise](https://github.com/reactphp/promise) +which resolves with a PSR-7 `ResponseInterface` object. -You will find a `Response` class -which implements the `PSR-7 ResponseInterface` in this project. -We use instantiation of this class in our projects, -but feel free to use any implemantation of the -`PSR-7 ResponseInterface` you prefer. +This projects ships a [`Response` class](#response) which implements the PSR-7 +`ResponseInterface`. In its most simple form, you can use it like this: ```php -$server = new Server($loop, function (ServerRequestInterface $request) { - return new Response( +$server = new React\Http\Server($loop, function (ServerRequestInterface $request) { + return new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -1374,6 +1376,10 @@ $server = new Server($loop, function (ServerRequestInterface $request) { }); ``` +We use this [`Response` class](#response) throughout our project examples, but +feel free to use any other implementation of the PSR-7 `ResponseInterface`. +See also the [`Response` class](#response) for more details. + #### Deferred response The example above returns the response directly, because it needs @@ -2331,6 +2337,53 @@ Notice that the [`Browser`](#browser) is an immutable object, i.e. this method actually returns a *new* [`Browser`](#browser) instance with the given setting applied. +### React\Http\Message + +#### Response + +The `Response` class can be used to +represent an outgoing server response message. + +```php +$response = new React\Http\Message\Response( + 200, + array( + 'Content-Type' => 'text/html' + ), + "Hello world!\n" +); +``` + +This class implements the +[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) +which in turn extends the +[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). + +> Internally, this class extends the underlying `\RingCentral\Psr7\Response` + class. The only difference is that this class will accept implemenations + of ReactPHPs `ReadableStreamInterface` for the `$body` argument. This base + class is considered an implementation detail that may change in the future. + +#### ServerRequest + +The `ServerRequest` class can be used to +respresent an incoming server request message. + +This class implements the +[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface) +which extends the +[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface) +which in turn extends the +[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). + +This is mostly used internally to represent each incoming request message. +Likewise, you can also use this class in test cases to test how your web +application reacts to certain HTTP requests. + +> Internally, this implementation builds on top of an existing outgoing + request message and only adds required server methods. This base class is + considered an implementation detail that may change in the future. + ### React\Http\Middleware #### StreamingRequestMiddleware @@ -2357,7 +2410,7 @@ $server = new React\Http\Server(array( $bytes += \count($chunk); }); $body->on('close', function () use (&$bytes, $resolve) { - $resolve(new React\Http\Response( + $resolve(new React\Http\Message\Response( 200, [], "Received $bytes bytes\n" diff --git a/examples/51-server-hello-world.php b/examples/51-server-hello-world.php index c0ad6741..f6903cff 100644 --- a/examples/51-server-hello-world.php +++ b/examples/51-server-hello-world.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/52-server-count-visitors.php b/examples/52-server-count-visitors.php index 1fa051f3..2b8e897c 100644 --- a/examples/52-server-count-visitors.php +++ b/examples/52-server-count-visitors.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/53-server-whatsmyip.php b/examples/53-server-whatsmyip.php index 512334eb..18f7504e 100644 --- a/examples/53-server-whatsmyip.php +++ b/examples/53-server-whatsmyip.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/54-server-query-parameter.php b/examples/54-server-query-parameter.php index aaee50e6..2786f380 100644 --- a/examples/54-server-query-parameter.php +++ b/examples/54-server-query-parameter.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/55-server-cookie-handling.php b/examples/55-server-cookie-handling.php index d96d4a85..6faf6be7 100644 --- a/examples/55-server-cookie-handling.php +++ b/examples/55-server-cookie-handling.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/56-server-sleep.php b/examples/56-server-sleep.php index 141db6ea..3da6963b 100644 --- a/examples/56-server-sleep.php +++ b/examples/56-server-sleep.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Promise\Promise; diff --git a/examples/57-server-error-handling.php b/examples/57-server-error-handling.php index 625fda17..c8e99ee4 100644 --- a/examples/57-server-error-handling.php +++ b/examples/57-server-error-handling.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Promise\Promise; diff --git a/examples/58-server-stream-response.php b/examples/58-server-stream-response.php index d246a237..518c2cb4 100644 --- a/examples/58-server-stream-response.php +++ b/examples/58-server-stream-response.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Stream\ThroughStream; diff --git a/examples/59-server-json-api.php b/examples/59-server-json-api.php index 79f87db4..8602a889 100644 --- a/examples/59-server-json-api.php +++ b/examples/59-server-json-api.php @@ -8,7 +8,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/61-server-hello-world-https.php b/examples/61-server-hello-world-https.php index 19eff50b..dfe3e941 100644 --- a/examples/61-server-hello-world-https.php +++ b/examples/61-server-hello-world-https.php @@ -2,7 +2,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/62-server-form-upload.php b/examples/62-server-form-upload.php index 85d948fc..d7eef4f3 100644 --- a/examples/62-server-form-upload.php +++ b/examples/62-server-form-upload.php @@ -10,11 +10,11 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\UploadedFileInterface; use React\EventLoop\Factory; +use React\Http\Message\Response; use React\Http\Middleware\LimitConcurrentRequestsMiddleware; use React\Http\Middleware\RequestBodyBufferMiddleware; use React\Http\Middleware\RequestBodyParserMiddleware; use React\Http\Middleware\StreamingRequestMiddleware; -use React\Http\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; diff --git a/examples/63-server-streaming-request.php b/examples/63-server-streaming-request.php index 6b9c8cec..9c1a9758 100644 --- a/examples/63-server-streaming-request.php +++ b/examples/63-server-streaming-request.php @@ -23,7 +23,7 @@ function (Psr\Http\Message\ServerRequestInterface $request) { }); $body->on('end', function () use ($resolve, &$bytes){ - $resolve(new React\Http\Response( + $resolve(new React\Http\Message\Response( 200, array( 'Content-Type' => 'text/plain' @@ -34,7 +34,7 @@ function (Psr\Http\Message\ServerRequestInterface $request) { // an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event $body->on('error', function (\Exception $exception) use ($resolve, &$bytes) { - $resolve(new React\Http\Response( + $resolve(new React\Http\Message\Response( 400, array( 'Content-Type' => 'text/plain' diff --git a/examples/71-server-http-proxy.php b/examples/71-server-http-proxy.php index 5b829a73..b959b7bf 100644 --- a/examples/71-server-http-proxy.php +++ b/examples/71-server-http-proxy.php @@ -5,7 +5,7 @@ use Psr\Http\Message\RequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use RingCentral\Psr7; diff --git a/examples/72-server-http-connect-proxy.php b/examples/72-server-http-connect-proxy.php index 6a0364e8..e786da76 100644 --- a/examples/72-server-http-connect-proxy.php +++ b/examples/72-server-http-connect-proxy.php @@ -5,7 +5,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Socket\Connector; use React\Socket\ConnectionInterface; diff --git a/examples/81-server-upgrade-echo.php b/examples/81-server-upgrade-echo.php index 6ae2ce8e..34e85f6c 100644 --- a/examples/81-server-upgrade-echo.php +++ b/examples/81-server-upgrade-echo.php @@ -19,7 +19,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Stream\ThroughStream; diff --git a/examples/82-server-upgrade-chat.php b/examples/82-server-upgrade-chat.php index ee4ce146..5e49ce37 100644 --- a/examples/82-server-upgrade-chat.php +++ b/examples/82-server-upgrade-chat.php @@ -21,7 +21,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Stream\CompositeStream; use React\Stream\ThroughStream; diff --git a/examples/99-server-benchmark-download.php b/examples/99-server-benchmark-download.php index bd4acde6..536f4515 100644 --- a/examples/99-server-benchmark-download.php +++ b/examples/99-server-benchmark-download.php @@ -10,7 +10,7 @@ use Evenement\EventEmitter; use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Stream\ReadableStreamInterface; use React\Stream\WritableStreamInterface; diff --git a/src/Io/RequestHeaderParser.php b/src/Io/RequestHeaderParser.php index f7f77e7e..53f7ff09 100644 --- a/src/Io/RequestHeaderParser.php +++ b/src/Io/RequestHeaderParser.php @@ -4,6 +4,7 @@ use Evenement\EventEmitter; use Psr\Http\Message\ServerRequestInterface; +use React\Http\Message\ServerRequest; use React\Socket\ConnectionInterface; use Exception; @@ -223,7 +224,7 @@ public function parseRequest($headers, $remoteSocketUri, $localSocketUri) $start['method'], $uri, $fields, - null, + '', $start['version'], $serverParams ); diff --git a/src/Io/StreamingServer.php b/src/Io/StreamingServer.php index 3ec791b2..1d41a9c3 100644 --- a/src/Io/StreamingServer.php +++ b/src/Io/StreamingServer.php @@ -6,7 +6,8 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\LoopInterface; -use React\Http\Response; +use React\Http\Message\Response; +use React\Http\Message\ServerRequest; use React\Promise; use React\Promise\CancellablePromiseInterface; use React\Promise\PromiseInterface; @@ -75,8 +76,7 @@ * [streaming request](#streaming-request) below for more details. * * @see \React\Http\Server - * @see Request - * @see Response + * @see \React\Http\Message\Response * @see self::listen() * @internal */ diff --git a/src/Message/Response.php b/src/Message/Response.php new file mode 100644 index 00000000..45d007ee --- /dev/null +++ b/src/Message/Response.php @@ -0,0 +1,66 @@ + 'text/html' + * ), + * "Hello world!\n" + * ); + * ``` + * + * This class implements the + * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) + * which in turn extends the + * [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). + * + * > Internally, this class extends the underlying `\RingCentral\Psr7\Response` + * class. The only difference is that this class will accept implemenations + * of ReactPHPs `ReadableStreamInterface` for the `$body` argument. This base + * class is considered an implementation detail that may change in the future. + * + * @see \Psr\Http\Message\ResponseInterface + */ +class Response extends Psr7Response +{ + /** + * @param int $status HTTP status code (e.g. 200/404) + * @param array $headers additional response headers + * @param string|ReadableStreamInterface|StreamInterface $body response body + * @param string $version HTTP protocol version (e.g. 1.1/1.0) + * @param ?string $reason custom HTTP response phrase + * @throws \InvalidArgumentException for an invalid body + */ + public function __construct( + $status = 200, + array $headers = array(), + $body = '', + $version = '1.1', + $reason = null + ) { + if ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { + $body = new HttpBodyStream($body, null); + } elseif (!\is_string($body) && !$body instanceof StreamInterface) { + throw new \InvalidArgumentException('Invalid response body given'); + } + + parent::__construct( + $status, + $headers, + $body, + $version, + $reason + ); + } +} diff --git a/src/Io/ServerRequest.php b/src/Message/ServerRequest.php similarity index 57% rename from src/Io/ServerRequest.php rename to src/Message/ServerRequest.php index 28a8c5db..b0d64498 100644 --- a/src/Io/ServerRequest.php +++ b/src/Message/ServerRequest.php @@ -1,25 +1,33 @@ Internally, this implementation builds on top of an existing outgoing + * request message and only adds required server methods. This base class is + * considered an implementation detail that may change in the future. * * @see ServerRequestInterface - * @internal */ class ServerRequest extends Request implements ServerRequestInterface { @@ -32,25 +40,40 @@ class ServerRequest extends Request implements ServerRequestInterface private $parsedBody; /** - * @param null|string $method HTTP method for the request. - * @param null|string|UriInterface $uri URI for the request. - * @param array $headers Headers for the message. - * @param string|resource|StreamInterface $body Message body. - * @param string $protocolVersion HTTP protocol version. - * @param array $serverParams server-side parameters - * - * @throws \InvalidArgumentException for an invalid URI + * @param string $method HTTP method for the request. + * @param string|UriInterface $url URL for the request. + * @param array $headers Headers for the message. + * @param string|ReadableStreamInterface|StreamInterface $body Message body. + * @param string $version HTTP protocol version. + * @param array $serverParams server-side parameters + * @throws \InvalidArgumentException for an invalid URL or body */ public function __construct( $method, - $uri, + $url, array $headers = array(), - $body = null, - $protocolVersion = '1.1', + $body = '', + $version = '1.1', $serverParams = array() ) { + $stream = null; + if ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { + $stream = $body; + $body = null; + } elseif (!\is_string($body) && !$body instanceof StreamInterface) { + throw new \InvalidArgumentException('Invalid server request body given'); + } + $this->serverParams = $serverParams; - parent::__construct($method, $uri, $headers, $body, $protocolVersion); + parent::__construct($method, $url, $headers, $body, $version); + + if ($stream !== null) { + $size = (int) $this->getHeaderLine('Content-Length'); + if (\strtolower($this->getHeaderLine('Transfer-Encoding')) === 'chunked') { + $size = null; + } + $this->stream = new HttpBodyStream($stream, $size); + } $query = $this->getUri()->getQuery(); if ($query !== '') { @@ -152,10 +175,6 @@ public function withoutAttribute($name) */ private function parseCookie($cookie) { - if ($cookie === '') { - return array(); - } - $cookieArray = \explode(';', $cookie); $result = array(); diff --git a/src/Response.php b/src/Response.php deleted file mode 100644 index 0964dac9..00000000 --- a/src/Response.php +++ /dev/null @@ -1,36 +0,0 @@ - 'text/plain' @@ -40,7 +40,7 @@ * * Each outgoing HTTP response message is always represented by the * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), - * see also following [response](#response) chapter for more details. + * see also following [response](#server-response) chapter for more details. * * In order to start listening for any incoming connections, the `Server` needs * to be attached to an instance of diff --git a/tests/FunctionalBrowserTest.php b/tests/FunctionalBrowserTest.php index 69c60ba7..3cf9293a 100644 --- a/tests/FunctionalBrowserTest.php +++ b/tests/FunctionalBrowserTest.php @@ -9,7 +9,7 @@ use React\Http\Browser; use React\Http\Message\ResponseException; use React\Http\Middleware\StreamingRequestMiddleware; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Promise\Promise; use React\Promise\Stream; diff --git a/tests/FunctionalServerTest.php b/tests/FunctionalServerTest.php index ba834082..3355b732 100644 --- a/tests/FunctionalServerTest.php +++ b/tests/FunctionalServerTest.php @@ -5,7 +5,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\Http\Middleware\LimitConcurrentRequestsMiddleware; use React\Http\Middleware\RequestBodyBufferMiddleware; -use React\Http\Response; +use React\Http\Message\Response; use React\Http\Server; use React\Socket\Server as Socket; use React\EventLoop\Factory; diff --git a/tests/Io/MiddlewareRunnerTest.php b/tests/Io/MiddlewareRunnerTest.php index f43231b0..eda61012 100644 --- a/tests/Io/MiddlewareRunnerTest.php +++ b/tests/Io/MiddlewareRunnerTest.php @@ -3,18 +3,18 @@ namespace React\Tests\Http\Io; use Clue\React\Block; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; use React\Http\Io\MiddlewareRunner; -use React\Http\Io\ServerRequest; +use React\Http\Message\ServerRequest; use React\Promise; +use React\Promise\CancellablePromiseInterface; +use React\Promise\PromiseInterface; use React\Tests\Http\Middleware\ProcessStack; use React\Tests\Http\TestCase; use RingCentral\Psr7\Response; -use Psr\Http\Message\RequestInterface; -use React\Promise\CancellablePromiseInterface; -use React\Promise\PromiseInterface; final class MiddlewareRunnerTest extends TestCase { diff --git a/tests/Io/MultipartParserTest.php b/tests/Io/MultipartParserTest.php index 91ec832d..14550f57 100644 --- a/tests/Io/MultipartParserTest.php +++ b/tests/Io/MultipartParserTest.php @@ -3,7 +3,7 @@ namespace React\Tests\Http\Io\Middleware; use React\Http\Io\MultipartParser; -use React\Http\Io\ServerRequest; +use React\Http\Message\ServerRequest; use React\Tests\Http\TestCase; final class MultipartParserTest extends TestCase diff --git a/tests/Io/StreamingServerTest.php b/tests/Io/StreamingServerTest.php index b903a850..5dff1f0c 100644 --- a/tests/Io/StreamingServerTest.php +++ b/tests/Io/StreamingServerTest.php @@ -3,9 +3,9 @@ namespace React\Tests\Http\Io; use Psr\Http\Message\ServerRequestInterface; -use React\Http\Io\StreamingServer; use React\EventLoop\Factory; -use React\Http\Response; +use React\Http\Io\StreamingServer; +use React\Http\Message\Response; use React\Promise\Promise; use React\Stream\ThroughStream; use React\Tests\Http\SocketServerStub; diff --git a/tests/Message/ResponseTest.php b/tests/Message/ResponseTest.php new file mode 100644 index 00000000..457618e9 --- /dev/null +++ b/tests/Message/ResponseTest.php @@ -0,0 +1,52 @@ +assertInstanceOf('RingCentral\Psr7\Stream', $response->getBody()); + } + + public function testConstructWithStreamingBodyWillReturnReadableBodyStream() + { + $response = new Response(200, array(), new ThroughStream()); + + $body = $response->getBody(); + $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); + $this->assertInstanceof('React\Stream\ReadableStreamInterface', $body); + $this->assertInstanceOf('React\Http\Io\HttpBodyStream', $body); + $this->assertNull($body->getSize()); + } + + public function testConstructWithHttpBodyStreamReturnsBodyAsIs() + { + $response = new Response( + 200, + array(), + $body = new HttpBodyStream(new ThroughStream(), 100) + ); + + $this->assertSame($body, $response->getBody()); + } + + public function testFloatBodyWillThrow() + { + $this->setExpectedException('InvalidArgumentException'); + new Response(200, array(), 1.0); + } + + public function testResourceBodyWillThrow() + { + $this->setExpectedException('InvalidArgumentException'); + new Response(200, array(), tmpfile()); + } +} diff --git a/tests/Io/ServerRequestTest.php b/tests/Message/ServerRequestTest.php similarity index 73% rename from tests/Io/ServerRequestTest.php rename to tests/Message/ServerRequestTest.php index 47346cd1..37cc1879 100644 --- a/tests/Io/ServerRequestTest.php +++ b/tests/Message/ServerRequestTest.php @@ -1,8 +1,10 @@ request->getCookieParams(); $this->assertEquals(array('hello' => 'world', 'react' => 'php'), $cookies); } + + public function testConstructWithStringRequestBodyReturnsStringBodyWithAutomaticSize() + { + $request = new ServerRequest( + 'GET', + 'http://localhost', + array(), + 'foo' + ); + + $body = $request->getBody(); + $this->assertSame(3, $body->getSize()); + $this->assertEquals('foo', (string) $body); + } + + public function testConstructWithHttpBodyStreamReturnsBodyAsIs() + { + $request = new ServerRequest( + 'GET', + 'http://localhost', + array(), + $body = new HttpBodyStream(new ThroughStream(), 100) + ); + + $this->assertSame($body, $request->getBody()); + } + + public function testConstructWithStreamingRequestBodyReturnsBodyWhichImplementsReadableStreamInterfaceWithSizeZeroDefault() + { + $request = new ServerRequest( + 'GET', + 'http://localhost', + array(), + new ThroughStream() + ); + + $body = $request->getBody(); + $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); + $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); + $this->assertSame(0, $body->getSize()); + } + + public function testConstructWithStreamingRequestBodyReturnsBodyWithSizeFromContentLengthHeader() + { + $request = new ServerRequest( + 'GET', + 'http://localhost', + array( + 'Content-Length' => 100 + ), + new ThroughStream() + ); + + $body = $request->getBody(); + $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); + $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); + $this->assertSame(100, $body->getSize()); + } + + public function testConstructWithStreamingRequestBodyReturnsBodyWithSizeUnknownForTransferEncodingChunked() + { + $request = new ServerRequest( + 'GET', + 'http://localhost', + array( + 'Transfer-Encoding' => 'Chunked' + ), + new ThroughStream() + ); + + $body = $request->getBody(); + $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); + $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); + $this->assertNull($body->getSize()); + } + + public function testConstructWithFloatRequestBodyThrows() + { + $this->setExpectedException('InvalidArgumentException'); + new ServerRequest( + 'GET', + 'http://localhost', + array(), + 1.0 + ); + } + + public function testConstructWithResourceRequestBodyThrows() + { + $this->setExpectedException('InvalidArgumentException'); + new ServerRequest( + 'GET', + 'http://localhost', + array(), + tmpfile() + ); + } } diff --git a/tests/Middleware/LimitConcurrentRequestsMiddlewareTest.php b/tests/Middleware/LimitConcurrentRequestsMiddlewareTest.php index b4c82390..7e537391 100644 --- a/tests/Middleware/LimitConcurrentRequestsMiddlewareTest.php +++ b/tests/Middleware/LimitConcurrentRequestsMiddlewareTest.php @@ -4,14 +4,14 @@ use Psr\Http\Message\ServerRequestInterface; use React\Http\Io\HttpBodyStream; -use React\Http\Io\ServerRequest; +use React\Http\Message\Response; +use React\Http\Message\ServerRequest; use React\Http\Middleware\LimitConcurrentRequestsMiddleware; use React\Promise\Deferred; use React\Promise\Promise; +use React\Promise\PromiseInterface; use React\Stream\ThroughStream; use React\Tests\Http\TestCase; -use React\Promise\PromiseInterface; -use React\Http\Response; final class LimitConcurrentRequestsMiddlewareTest extends TestCase { diff --git a/tests/Middleware/RequestBodyBufferMiddlewareTest.php b/tests/Middleware/RequestBodyBufferMiddlewareTest.php index 98fdfbec..9889f501 100644 --- a/tests/Middleware/RequestBodyBufferMiddlewareTest.php +++ b/tests/Middleware/RequestBodyBufferMiddlewareTest.php @@ -6,9 +6,9 @@ use Psr\Http\Message\ServerRequestInterface; use React\EventLoop\Factory; use React\Http\Io\HttpBodyStream; -use React\Http\Io\ServerRequest; +use React\Http\Message\Response; +use React\Http\Message\ServerRequest; use React\Http\Middleware\RequestBodyBufferMiddleware; -use React\Http\Response; use React\Stream\ThroughStream; use React\Tests\Http\TestCase; use RingCentral\Psr7\BufferStream; diff --git a/tests/Middleware/RequestBodyParserMiddlewareTest.php b/tests/Middleware/RequestBodyParserMiddlewareTest.php index 994d562c..989abc81 100644 --- a/tests/Middleware/RequestBodyParserMiddlewareTest.php +++ b/tests/Middleware/RequestBodyParserMiddlewareTest.php @@ -3,7 +3,7 @@ namespace React\Tests\Http\Middleware; use Psr\Http\Message\ServerRequestInterface; -use React\Http\Io\ServerRequest; +use React\Http\Message\ServerRequest; use React\Http\Middleware\RequestBodyParserMiddleware; use React\Tests\Http\TestCase; diff --git a/tests/Middleware/StreamingRequestMiddlewareTest.php b/tests/Middleware/StreamingRequestMiddlewareTest.php index c78ab3af..c41e86b6 100644 --- a/tests/Middleware/StreamingRequestMiddlewareTest.php +++ b/tests/Middleware/StreamingRequestMiddlewareTest.php @@ -3,8 +3,8 @@ namespace React\Tests\Http\Middleware; use React\Http\Middleware\StreamingRequestMiddleware; -use React\Http\Io\ServerRequest; -use React\Http\Response; +use React\Http\Message\Response; +use React\Http\Message\ServerRequest; use React\Tests\Http\TestCase; class StreamingRequestMiddlewareTest extends TestCase diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php deleted file mode 100644 index 146278f1..00000000 --- a/tests/ResponseTest.php +++ /dev/null @@ -1,21 +0,0 @@ -assertInstanceOf('React\Http\Io\HttpBodyStream', $response->getBody()); - } - - public function testStringBodyWillBePsr7Stream() - { - $response = new Response(200, array(), 'hello'); - $this->assertInstanceOf('RingCentral\Psr7\Stream', $response->getBody()); - } -} diff --git a/tests/benchmark-middleware-runner.php b/tests/benchmark-middleware-runner.php index e7df2d93..3f1dacaf 100644 --- a/tests/benchmark-middleware-runner.php +++ b/tests/benchmark-middleware-runner.php @@ -2,8 +2,8 @@ use Psr\Http\Message\ServerRequestInterface; use React\Http\Io\MiddlewareRunner; -use React\Http\Io\ServerRequest; -use React\Http\Response; +use React\Http\Message\Response; +use React\Http\Message\ServerRequest; const ITERATIONS = 5000; const MIDDLEWARE_COUNT = 512; @@ -17,7 +17,7 @@ for ($i = 0; $i < MIDDLEWARE_COUNT; $i++) { $middlewareList[] = $middleware; } -$middlewareList[] = function (ServerRequestInterface $request, $next) { +$middlewareList[] = function (ServerRequestInterface $request) { return new Response(545); }; $middlewareRunner = new MiddlewareRunner($middlewareList);