diff --git a/README.md b/README.md index 768b3f8c..126fdcaf 100644 --- a/README.md +++ b/README.md @@ -87,22 +87,17 @@ Once [installed](#install), you can use the following code to access a HTTP webserver and send some simple HTTP GET requests: ```php -$loop = React\EventLoop\Factory::create(); -$client = new React\Http\Browser($loop); +$client = new React\Http\Browser(); $client->get('http://www.google.com/')->then(function (Psr\Http\Message\ResponseInterface $response) { var_dump($response->getHeaders(), (string)$response->getBody()); }); - -$loop->run(); ``` This is an HTTP server which responds with `Hello World!` to every request. ```php -$loop = React\EventLoop\Factory::create(); - -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -112,10 +107,8 @@ $server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestI ); }); -$socket = new React\Socket\Server(8080, $loop); +$socket = new React\Socket\Server(8080); $server->listen($socket); - -$loop->run(); ``` See also the [examples](examples/). @@ -208,7 +201,7 @@ clean up any underlying resources. ```php $promise = $browser->get($url); -$loop->addTimer(2.0, function () use ($promise) { +Loop::addTimer(2.0, function () use ($promise) { $promise->cancel(); }); ``` @@ -266,9 +259,9 @@ like this: ```php $browser = new React\Http\Browser( - $loop, + null, new React\Socket\Connector( - $loop, + null, array( 'timeout' => 5 ) @@ -373,13 +366,12 @@ The resulting blocking code could look something like this: ```php use Clue\React\Block; -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); $promise = $browser->get('http://example.com/'); try { - $response = Block\await($promise, $loop); + $response = Block\await($promise, Loop::get()); // response successfully received } catch (Exception $e) { // an error occured while performing the request @@ -394,7 +386,7 @@ $promises = array( $browser->get('http://www.example.org/'), ); -$responses = Block\awaitAll($promises, $loop); +$responses = Block\awaitAll($promises, Loop::get()); ``` Please refer to [clue/reactphp-block](https://github.com/clue/reactphp-block#readme) for more details. @@ -584,7 +576,7 @@ matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -610,15 +602,15 @@ protocol, such as plain HTTP and TLS-encrypted HTTPS. ```php $proxy = new Clue\React\HttpProxy\ProxyConnector( 'http://127.0.0.1:8080', - new React\Socket\Connector($loop) + new React\Socket\Connector() ); -$connector = new React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'tcp' => $proxy, 'dns' => false )); -$browser = new React\Http\Browser($loop, $connector); +$browser = new React\Http\Browser(null, $connector); ``` See also the [HTTP CONNECT proxy example](examples/11-client-http-connect-proxy.php). @@ -637,15 +629,15 @@ only, this can technically be used to tunnel any TCP/IP-based protocol. ```php $proxy = new Clue\React\Socks\Client( 'socks://127.0.0.1:1080', - new React\Socket\Connector($loop) + new React\Socket\Connector() ); -$connector = new React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'tcp' => $proxy, 'dns' => false )); -$browser = new React\Http\Browser($loop, $connector); +$browser = new React\Http\Browser(null, $connector); ``` See also the [SOCKS proxy example](examples/12-client-socks-proxy.php). @@ -667,14 +659,14 @@ from the outside (database behind firewall) and as such can also be used for plain HTTP and TLS-encrypted HTTPS. ```php -$proxy = new Clue\React\SshProxy\SshSocksConnector('me@localhost:22', $loop); +$proxy = new Clue\React\SshProxy\SshSocksConnector('me@localhost:22', Loop::get()); -$connector = new React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'tcp' => $proxy, 'dns' => false )); -$browser = new React\Http\Browser($loop, $connector); +$browser = new React\Http\Browser(null, $connector); ``` See also the [SSH proxy example](examples/13-client-ssh-proxy.php). @@ -692,10 +684,10 @@ no longer be used to establish the connection: ```php $connector = new React\Socket\FixedUriConnector( 'unix:///var/run/docker.sock', - new React\Socket\UnixConnector($loop) + new React\Socket\UnixConnector() ); -$browser = new Browser($loop, $connector); +$browser = new Browser(null, $connector); $client->get('http://localhost/info')->then(function (Psr\Http\Message\ResponseInterface $response) { var_dump($response->getHeaders(), (string)$response->getBody()); @@ -718,7 +710,7 @@ the constructor and will be invoked with the respective [request](#server-reques object and expects a [response](#server-response) object in return: ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -737,6 +729,12 @@ 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](#server-response) chapter for more details. +This class takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use for this object. You can use a `null` value +here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). +This value SHOULD NOT be given unless you're sure you want to explicitly use a +given event loop instance. + In order to start listening for any incoming connections, the `Server` needs to be attached to an instance of [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) @@ -746,9 +744,9 @@ chapter. In its most simple form, you can attach this to a to start a plaintext HTTP server like this: ```php -$server = new React\Http\Server($loop, $handler); +$server = new React\Http\Server($handler); -$socket = new React\Socket\Server('0.0.0.0:8080', $loop); +$socket = new React\Socket\Server('0.0.0.0:8080'); $server->listen($socket); ``` @@ -817,7 +815,6 @@ once like this: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request @@ -843,7 +840,6 @@ in memory: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), $handler ); @@ -872,9 +868,9 @@ messages. In its most common form, you can attach this to a order to start a plaintext HTTP server like this: ```php -$server = new React\Http\Server($loop, $handler); +$server = new React\Http\Server($handler); -$socket = new React\Socket\Server('0.0.0.0:8080', $loop); +$socket = new React\Socket\Server('0.0.0.0:8080'); $server->listen($socket); ``` @@ -898,9 +894,9 @@ using a secure TLS listen address, a certificate file and optional `passphrase` like this: ```php -$server = new React\Http\Server($loop, $handler); +$server = new React\Http\Server($handler); -$socket = new React\Socket\Server('tls://0.0.0.0:8443', $loop, array( +$socket = new React\Socket\Server('tls://0.0.0.0:8443', null, array( 'local_cert' => __DIR__ . '/localhost.pem' )); $server->listen($socket); @@ -923,7 +919,7 @@ which in turn extends the and will be passed to the callback function like this. ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $body = "The method of the request is: " . $request->getMethod(); $body .= "The requested path is: " . $request->getUri()->getPath(); @@ -966,7 +962,7 @@ The following parameters are currently available: Set to 'on' if the request used HTTPS, otherwise it won't be set ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $body = "Your IP is: " . $request->getServerParams()['REMOTE_ADDR']; return new React\Http\Message\Response( @@ -991,7 +987,7 @@ The `getQueryParams(): array` method can be used to get the query parameters similiar to the `$_GET` variable. ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $queryParams = $request->getQueryParams(); $body = 'The query parameter "foo" is not set. Click the following link '; @@ -1045,7 +1041,7 @@ By default, this method will only return parsed data for requests using request headers (commonly used for `POST` requests for HTML form submission data). ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $name = $request->getParsedBody()['name'] ?? 'anonymous'; return new React\Http\Message\Response( @@ -1069,7 +1065,7 @@ an XML (`Content-Type: application/xml`) request body (which is commonly used fo `POST`, `PUT` or `PATCH` requests in JSON-based or RESTful/RESTish APIs). ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $data = json_decode((string)$request->getBody()); $name = $data->name ?? 'anonymous'; @@ -1092,7 +1088,7 @@ This array will only be filled when using the `Content-Type: multipart/form-data request header (commonly used for `POST` requests for HTML file uploads). ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $files = $request->getUploadedFiles(); $name = isset($files['avatar']) ? $files['avatar']->getClientFilename() : 'nothing'; @@ -1166,7 +1162,6 @@ gives you access to the incoming request body as the individual chunks arrive: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), function (Psr\Http\Message\ServerRequestInterface $request) { $body = $request->getBody(); @@ -1240,7 +1235,6 @@ may be unknown (`null`) when using `Transfer-Encoding: chunked` for HTTP/1.1 req ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), function (Psr\Http\Message\ServerRequestInterface $request) { $size = $request->getBody()->getSize(); @@ -1313,7 +1307,7 @@ The `getCookieParams(): string[]` method can be used to get all cookies sent with the current request. ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $key = 'react\php'; if (isset($request->getCookieParams()[$key])) { @@ -1385,7 +1379,7 @@ This projects ships a [`Response` class](#response) which implements the In its most simple form, you can use it like this: ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1413,9 +1407,9 @@ To prevent this you SHOULD use a This example shows how such a long-term action could look like: ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) use ($loop) { - return new Promise(function ($resolve, $reject) use ($loop) { - $loop->addTimer(1.5, function() use ($resolve) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { + return new Promise(function ($resolve, $reject) { + Loop::addTimer(1.5, function() use ($resolve) { $response = new React\Http\Message\Response( 200, array( @@ -1451,15 +1445,15 @@ Note that other implementations of the may only support strings. ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) use ($loop) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $stream = new ThroughStream(); - $timer = $loop->addPeriodicTimer(0.5, function () use ($stream) { + $timer = Loop::addPeriodicTimer(0.5, function () use ($stream) { $stream->write(microtime(true) . PHP_EOL); }); - $loop->addTimer(5, function() use ($loop, $timer, $stream) { - $loop->cancelTimer($timer); + Loop::addTimer(5, function() use ($timer, $stream) { + Loop::cancelTimer($timer); $stream->end(); }); @@ -1543,7 +1537,7 @@ added automatically. This is the most common use case, for example when using a `string` response body like this: ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1562,10 +1556,10 @@ response messages will contain the plain response body. If you know the length of your streaming response body, you MAY want to specify it explicitly like this: ```php -$server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) use ($loop) { +$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { $stream = new ThroughStream(); - $loop->addTimer(2.0, function () use ($stream) { + Loop::addTimer(2.0, function () use ($stream) { $stream->end("Hello World!\n"); }); @@ -1638,7 +1632,7 @@ A `Server: ReactPHP/1` response header will be added automatically. You can add a custom `Server` response header like this: ```php -$server = new React\Http\Server($loop, function (ServerRequestInterface $request) { +$server = new React\Http\Server(function (ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1653,7 +1647,7 @@ don't want to expose the underlying server software), you can use an empty string value like this: ```php -$server = new React\Http\Server($loop, function (ServerRequestInterface $request) { +$server = new React\Http\Server(function (ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1668,7 +1662,7 @@ date and time if none is given. You can add a custom `Date` response header like this: ```php -$server = new React\Http\Server($loop, function (ServerRequestInterface $request) { +$server = new React\Http\Server(function (ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1683,7 +1677,7 @@ don't have an appropriate clock to rely on), you can use an empty string value like this: ```php -$server = new React\Http\Server($loop, function (ServerRequestInterface $request) { +$server = new React\Http\Server(function (ServerRequestInterface $request) { return new React\Http\Message\Response( 200, array( @@ -1767,7 +1761,6 @@ header (`Request-Time`) and a final request handler that always returns a 200 co ```php $server = new React\Http\Server( - $loop, function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { $request = $request->withHeader('Request-Time', time()); return $next($request); @@ -1792,7 +1785,6 @@ In order to simplify handling both paths, you can simply wrap this in a ```php $server = new React\Http\Server( - $loop, function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { $promise = React\Promise\resolve($next($request)); return $promise->then(function (ResponseInterface $response) { @@ -1815,7 +1807,6 @@ handling logic (or logging etc.) by wrapping this in a ```php $server = new React\Http\Server( - $loop, function (Psr\Http\Message\ServerRequestInterface $request, callable $next) { $promise = new React\Promise\Promise(function ($resolve) use ($next, $request) { $resolve($next($request)); @@ -1873,20 +1864,23 @@ feel free to add it to this list. The `React\Http\Browser` is responsible for sending HTTP requests to your HTTP server and keeps track of pending incoming HTTP responses. -It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage). ```php -$loop = React\EventLoop\Factory::create(); - -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); ``` +This class takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use for this object. You can use a `null` value +here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). +This value SHOULD NOT be given unless you're sure you want to explicitly use a +given event loop instance. + If you need custom connector settings (DNS resolution, TLS parameters, timeouts, proxy servers etc.), you can explicitly pass a custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): ```php -$connector = new React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' @@ -1897,7 +1891,7 @@ $connector = new React\Socket\Connector($loop, array( ) )); -$browser = new React\Http\Browser($loop, $connector); +$browser = new React\Http\Browser(null, $connector); ``` > Note that the browser class is final and shouldn't be extended, it is likely to be marked final in a future release. @@ -1959,7 +1953,7 @@ matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -2002,7 +1996,7 @@ matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -2036,7 +2030,7 @@ matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -2084,7 +2078,7 @@ explicitly pass in a matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -2146,7 +2140,7 @@ explicitly pass in a matching `Content-Length` request header like so: ```php $body = new React\Stream\ThroughStream(); -$loop->addTimer(1.0, function () use ($body) { +Loop::addTimer(1.0, function () use ($body) { $body->end("hello world"); }); @@ -2513,7 +2507,6 @@ than 10 handlers will be invoked at once: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\LimitConcurrentRequestsMiddleware(10), $handler ); @@ -2525,7 +2518,6 @@ to limit the total number of requests that can be buffered at once: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request @@ -2540,7 +2532,6 @@ processes one request after another without any concurrency: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request @@ -2594,7 +2585,6 @@ Usage: ```php $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB @@ -2656,7 +2646,6 @@ $handler = function (Psr\Http\Message\ServerRequestInterface $request) { }; $server = new React\Http\Server( - $loop, new React\Http\Middleware\StreamingRequestMiddleware(), new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB diff --git a/composer.json b/composer.json index 6924ebff..6673b232 100644 --- a/composer.json +++ b/composer.json @@ -29,11 +29,11 @@ "php": ">=5.3.0", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "psr/http-message": "^1.0", - "react/event-loop": "^1.0 || ^0.5", + "react/event-loop": "^1.2", "react/promise": "^2.3 || ^1.2.1", "react/promise-stream": "^1.1", - "react/socket": "^1.6", - "react/stream": "^1.1", + "react/socket": "^1.8", + "react/stream": "^1.2", "ringcentral/psr7": "^1.2" }, "require-dev": { diff --git a/examples/01-client-get-request.php b/examples/01-client-get-request.php index 31a82606..8e232398 100644 --- a/examples/01-client-get-request.php +++ b/examples/01-client-get-request.php @@ -5,11 +5,8 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $client->get('http://google.com/')->then(function (ResponseInterface $response) { var_dump($response->getHeaders(), (string)$response->getBody()); }); - -$loop->run(); diff --git a/examples/02-client-concurrent-requests.php b/examples/02-client-concurrent-requests.php index 5a9e4258..dca1d9c1 100644 --- a/examples/02-client-concurrent-requests.php +++ b/examples/02-client-concurrent-requests.php @@ -5,8 +5,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $client->head('http://www.github.com/clue/http-react')->then(function (ResponseInterface $response) { var_dump($response->getHeaders(), (string)$response->getBody()); @@ -19,5 +18,3 @@ $client->get('http://www.lueck.tv/psocksd')->then(function (ResponseInterface $response) { var_dump($response->getHeaders(), (string)$response->getBody()); }); - -$loop->run(); diff --git a/examples/03-client-request-any.php b/examples/03-client-request-any.php index 881dabfc..a3bd2831 100644 --- a/examples/03-client-request-any.php +++ b/examples/03-client-request-any.php @@ -8,8 +8,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $promises = array( $client->head('http://www.github.com/clue/http-react'), @@ -28,5 +27,3 @@ var_dump($response->getHeaders()); echo PHP_EOL . $response->getBody(); }); - -$loop->run(); diff --git a/examples/04-client-post-json.php b/examples/04-client-post-json.php index 818dc9bc..400b1a13 100644 --- a/examples/04-client-post-json.php +++ b/examples/04-client-post-json.php @@ -5,8 +5,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $data = array( 'name' => array( @@ -25,5 +24,3 @@ )->then(function (ResponseInterface $response) { echo (string)$response->getBody(); }, 'printf'); - -$loop->run(); diff --git a/examples/05-client-put-xml.php b/examples/05-client-put-xml.php index 7c23182d..05804f23 100644 --- a/examples/05-client-put-xml.php +++ b/examples/05-client-put-xml.php @@ -5,8 +5,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $xml = new SimpleXMLElement(''); $child = $xml->addChild('user'); @@ -22,5 +21,3 @@ )->then(function (ResponseInterface $response) { echo (string)$response->getBody(); }, 'printf'); - -$loop->run(); diff --git a/examples/11-client-http-connect-proxy.php b/examples/11-client-http-connect-proxy.php index 53d2e91a..afa22e83 100644 --- a/examples/11-client-http-connect-proxy.php +++ b/examples/11-client-http-connect-proxy.php @@ -6,29 +6,24 @@ // $ php examples/72-server-http-connect-proxy.php 8080 // $ php examples/11-client-http-connect-proxy.php -use React\Http\Browser; use Clue\React\HttpProxy\ProxyConnector as HttpConnectClient; use Psr\Http\Message\ResponseInterface; -use React\EventLoop\Factory as LoopFactory; +use React\Http\Browser; use React\Socket\Connector; require __DIR__ . '/../vendor/autoload.php'; -$loop = LoopFactory::create(); - // create a new HTTP CONNECT proxy client which connects to a HTTP CONNECT proxy server listening on localhost:8080 -$proxy = new HttpConnectClient('127.0.0.1:8080', new Connector($loop)); +$proxy = new HttpConnectClient('127.0.0.1:8080', new Connector()); // create a Browser object that uses the HTTP CONNECT proxy client for connections -$connector = new Connector($loop, array( +$connector = new Connector(null, array( 'tcp' => $proxy, 'dns' => false )); -$browser = new Browser($loop, $connector); +$browser = new Browser(null, $connector); // demo fetching HTTP headers (or bail out otherwise) $browser->get('https://www.google.com/')->then(function (ResponseInterface $response) { echo RingCentral\Psr7\str($response); }, 'printf'); - -$loop->run(); diff --git a/examples/12-client-socks-proxy.php b/examples/12-client-socks-proxy.php index 49827fa2..ec2375c5 100644 --- a/examples/12-client-socks-proxy.php +++ b/examples/12-client-socks-proxy.php @@ -3,29 +3,24 @@ // not already running a SOCKS proxy server? // Try LeProxy.org or this: `ssh -D 1080 localhost` -use React\Http\Browser; use Clue\React\Socks\Client as SocksClient; use Psr\Http\Message\ResponseInterface; -use React\EventLoop\Factory as LoopFactory; +use React\Http\Browser; use React\Socket\Connector; require __DIR__ . '/../vendor/autoload.php'; -$loop = LoopFactory::create(); - // create a new SOCKS proxy client which connects to a SOCKS proxy server listening on localhost:1080 -$proxy = new SocksClient('127.0.0.1:1080', new Connector($loop)); +$proxy = new SocksClient('127.0.0.1:1080', new Connector()); // create a Browser object that uses the SOCKS proxy client for connections -$connector = new Connector($loop, array( +$connector = new Connector(null, array( 'tcp' => $proxy, 'dns' => false )); -$browser = new Browser($loop, $connector); +$browser = new Browser(null, $connector); // demo fetching HTTP headers (or bail out otherwise) $browser->get('https://www.google.com/')->then(function (ResponseInterface $response) { echo RingCentral\Psr7\str($response); }, 'printf'); - -$loop->run(); diff --git a/examples/13-client-ssh-proxy.php b/examples/13-client-ssh-proxy.php index d0424fea..d4c8dcea 100644 --- a/examples/13-client-ssh-proxy.php +++ b/examples/13-client-ssh-proxy.php @@ -1,29 +1,25 @@ $proxy, 'dns' => false )); -$browser = new Browser($loop, $connector); +$browser = new Browser(null, $connector); // demo fetching HTTP headers (or bail out otherwise) $browser->get('https://www.google.com/')->then(function (ResponseInterface $response) { echo RingCentral\Psr7\str($response); }, 'printf'); - -$loop->run(); diff --git a/examples/14-client-unix-domain-sockets.php b/examples/14-client-unix-domain-sockets.php index 8881321e..f60dd9f7 100644 --- a/examples/14-client-unix-domain-sockets.php +++ b/examples/14-client-unix-domain-sockets.php @@ -1,27 +1,22 @@ get('http://localhost/info')->then(function (ResponseInterface $response) { echo Psr7\str($response); }, 'printf'); - -$loop->run(); diff --git a/examples/21-client-request-streaming-to-stdout.php b/examples/21-client-request-streaming-to-stdout.php index b7873775..3d2110a2 100644 --- a/examples/21-client-request-streaming-to-stdout.php +++ b/examples/21-client-request-streaming-to-stdout.php @@ -13,11 +13,10 @@ exit(1); } -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); -$out = new WritableResourceStream(STDOUT, $loop); -$info = new WritableResourceStream(STDERR, $loop); +$out = new WritableResourceStream(STDOUT); +$info = new WritableResourceStream(STDERR); $url = isset($argv[1]) ? $argv[1] : 'http://google.com/'; $info->write('Requesting ' . $url . '…' . PHP_EOL); @@ -29,5 +28,3 @@ assert($body instanceof ReadableStreamInterface); $body->pipe($out); }, 'printf'); - -$loop->run(); diff --git a/examples/22-client-stream-upload-from-stdin.php b/examples/22-client-stream-upload-from-stdin.php index 4a36df91..a0857feb 100644 --- a/examples/22-client-stream-upload-from-stdin.php +++ b/examples/22-client-stream-upload-from-stdin.php @@ -1,7 +1,7 @@ post($url, array(), $in)->then(function (ResponseInterface $response) { echo 'Received' . PHP_EOL . Psr7\str($response); }, 'printf'); - -$loop->run(); diff --git a/examples/51-server-hello-world.php b/examples/51-server-hello-world.php index f6903cff..2cfd5649 100644 --- a/examples/51-server-hello-world.php +++ b/examples/51-server-hello-world.php @@ -1,15 +1,12 @@ listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/52-server-count-visitors.php b/examples/52-server-count-visitors.php index 2b8e897c..ae173bbd 100644 --- a/examples/52-server-count-visitors.php +++ b/examples/52-server-count-visitors.php @@ -1,16 +1,13 @@ listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/53-server-whatsmyip.php b/examples/53-server-whatsmyip.php index 18f7504e..82f34742 100644 --- a/examples/53-server-whatsmyip.php +++ b/examples/53-server-whatsmyip.php @@ -1,15 +1,12 @@ getServerParams()['REMOTE_ADDR']; return new Response( @@ -21,9 +18,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/54-server-query-parameter.php b/examples/54-server-query-parameter.php index 2786f380..dbddfbc0 100644 --- a/examples/54-server-query-parameter.php +++ b/examples/54-server-query-parameter.php @@ -1,15 +1,12 @@ getQueryParams(); $body = 'The query parameter "foo" is not set. Click the following link '; @@ -28,9 +25,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/55-server-cookie-handling.php b/examples/55-server-cookie-handling.php index 6faf6be7..55370c3b 100644 --- a/examples/55-server-cookie-handling.php +++ b/examples/55-server-cookie-handling.php @@ -1,15 +1,12 @@ getCookieParams()[$key])) { @@ -34,9 +31,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/56-server-sleep.php b/examples/56-server-sleep.php index 3da6963b..9f149c4c 100644 --- a/examples/56-server-sleep.php +++ b/examples/56-server-sleep.php @@ -1,18 +1,16 @@ addTimer(1.5, function() use ($resolve) { +$server = new Server(function (ServerRequestInterface $request) { + return new Promise(function ($resolve, $reject) { + Loop::addTimer(1.5, function() use ($resolve) { $response = new Response( 200, array( @@ -25,9 +23,7 @@ }); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/57-server-error-handling.php b/examples/57-server-error-handling.php index c8e99ee4..6952a559 100644 --- a/examples/57-server-error-handling.php +++ b/examples/57-server-error-handling.php @@ -1,17 +1,14 @@ listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/58-server-stream-response.php b/examples/58-server-stream-response.php index 518c2cb4..941ded1f 100644 --- a/examples/58-server-stream-response.php +++ b/examples/58-server-stream-response.php @@ -1,16 +1,14 @@ getMethod() !== 'GET' || $request->getUri()->getPath() !== '/') { return new Response(404); } @@ -18,18 +16,18 @@ $stream = new ThroughStream(); // send some data every once in a while with periodic timer - $timer = $loop->addPeriodicTimer(0.5, function () use ($stream) { + $timer = Loop::addPeriodicTimer(0.5, function () use ($stream) { $stream->write(microtime(true) . PHP_EOL); }); // demo for ending stream after a few seconds - $loop->addTimer(5.0, function() use ($stream) { + Loop::addTimer(5.0, function() use ($stream) { $stream->end(); }); // stop timer if stream is closed (such as when connection is closed) - $stream->on('close', function () use ($loop, $timer) { - $loop->cancelTimer($timer); + $stream->on('close', function () use ($timer) { + Loop::cancelTimer($timer); }); return new Response( @@ -41,9 +39,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/59-server-json-api.php b/examples/59-server-json-api.php index 8602a889..c1b4d305 100644 --- a/examples/59-server-json-api.php +++ b/examples/59-server-json-api.php @@ -7,15 +7,12 @@ // $ curl -v http://localhost:8080/ -H 'Content-Type: application/json' -d '{"name":"Alice"}' use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Factory; use React\Http\Message\Response; use React\Http\Server; require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - -$server = new Server($loop, function (ServerRequestInterface $request) { +$server = new Server(function (ServerRequestInterface $request) { if ($request->getHeaderLine('Content-Type') !== 'application/json') { return new Response( 415, // Unsupported Media Type @@ -56,9 +53,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/61-server-hello-world-https.php b/examples/61-server-hello-world-https.php index dfe3e941..5b671618 100644 --- a/examples/61-server-hello-world-https.php +++ b/examples/61-server-hello-world-https.php @@ -1,15 +1,12 @@ isset($argv[2]) ? $argv[2] : __DIR__ . '/localhost.pem' )); $server->listen($socket); @@ -28,5 +25,3 @@ //$socket->on('error', 'printf'); echo 'Listening on ' . str_replace('tls:', 'https:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/62-server-form-upload.php b/examples/62-server-form-upload.php index d7eef4f3..b1f0d8ee 100644 --- a/examples/62-server-form-upload.php +++ b/examples/62-server-form-upload.php @@ -9,7 +9,6 @@ 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; @@ -19,8 +18,6 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - $handler = function (ServerRequestInterface $request) { if ($request->getMethod() === 'POST') { // Take form input values from POST values (for illustration purposes only!) @@ -125,7 +122,6 @@ // Note how this example explicitly uses the advanced `StreamingRequestMiddleware` to apply // custom request buffering limits below before running our request handler. $server = new Server( - $loop, new StreamingRequestMiddleware(), new LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers, queue otherwise new RequestBodyBufferMiddleware(8 * 1024 * 1024), // 8 MiB max, ignore body otherwise @@ -133,9 +129,7 @@ $handler ); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', null); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/63-server-streaming-request.php b/examples/63-server-streaming-request.php index 45eb0dea..c2416e15 100644 --- a/examples/63-server-streaming-request.php +++ b/examples/63-server-streaming-request.php @@ -1,16 +1,11 @@ getBody(); @@ -49,9 +44,7 @@ function (Psr\Http\Message\ServerRequestInterface $request) { $server->on('error', 'printf'); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/71-server-http-proxy.php b/examples/71-server-http-proxy.php index b959b7bf..95c2f411 100644 --- a/examples/71-server-http-proxy.php +++ b/examples/71-server-http-proxy.php @@ -11,13 +11,11 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - // Note how this example uses the `Server` without the `StreamingRequestMiddleware`. // This means that this proxy buffers the whole request before "processing" it. // As such, this is store-and-forward proxy. This could also use the advanced // `StreamingRequestMiddleware` to forward the incoming request as it comes in. -$server = new Server($loop, function (RequestInterface $request) { +$server = new Server(function (RequestInterface $request) { if (strpos($request->getRequestTarget(), '://') === false) { return new Response( 400, @@ -48,9 +46,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/72-server-http-connect-proxy.php b/examples/72-server-http-connect-proxy.php index e786da76..a1f33983 100644 --- a/examples/72-server-http-connect-proxy.php +++ b/examples/72-server-http-connect-proxy.php @@ -4,7 +4,6 @@ // $ curl -v --proxy http://localhost:8080 https://reactphp.org/ use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Factory; use React\Http\Message\Response; use React\Http\Server; use React\Socket\Connector; @@ -12,14 +11,13 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); -$connector = new Connector($loop); +$connector = new Connector(); // Note how this example uses the `Server` without the `StreamingRequestMiddleware`. // Unlike the plain HTTP proxy, the CONNECT method does not contain a body // and we establish an end-to-end connection over the stream object, so this // doesn't have to store any payload data in memory at all. -$server = new Server($loop, function (ServerRequestInterface $request) use ($connector) { +$server = new Server(function (ServerRequestInterface $request) use ($connector) { if ($request->getMethod() !== 'CONNECT') { return new Response( 405, @@ -53,9 +51,7 @@ function ($e) { ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/81-server-upgrade-echo.php b/examples/81-server-upgrade-echo.php index 34e85f6c..6a20181a 100644 --- a/examples/81-server-upgrade-echo.php +++ b/examples/81-server-upgrade-echo.php @@ -18,19 +18,17 @@ */ use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Factory; +use React\EventLoop\Loop; use React\Http\Message\Response; use React\Http\Server; use React\Stream\ThroughStream; require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - // Note how this example uses the `Server` without the `StreamingRequestMiddleware`. // The initial incoming request does not contain a body and we upgrade to a // stream object below. -$server = new Server($loop, function (ServerRequestInterface $request) use ($loop) { +$server = new Server(function (ServerRequestInterface $request) { if ($request->getHeaderLine('Upgrade') !== 'echo' || $request->getProtocolVersion() === '1.0') { return new Response( 426, @@ -46,7 +44,7 @@ // this means that any Upgraded data will simply be sent back to the client $stream = new ThroughStream(); - $loop->addTimer(0, function () use ($stream) { + Loop::addTimer(0, function () use ($stream) { $stream->write("Hello! Anything you send will be piped back." . PHP_EOL); }); @@ -59,9 +57,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/82-server-upgrade-chat.php b/examples/82-server-upgrade-chat.php index 5e49ce37..2c6f08a8 100644 --- a/examples/82-server-upgrade-chat.php +++ b/examples/82-server-upgrade-chat.php @@ -20,7 +20,7 @@ */ use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Factory; +use React\EventLoop\Loop; use React\Http\Message\Response; use React\Http\Server; use React\Stream\CompositeStream; @@ -28,8 +28,6 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - // simply use a shared duplex ThroughStream for all clients // it will simply emit any data that is sent to it // this means that any Upgraded data will simply be sent back to the client @@ -38,7 +36,7 @@ // Note how this example uses the `Server` without the `StreamingRequestMiddleware`. // The initial incoming request does not contain a body and we upgrade to a // stream object below. -$server = new Server($loop, function (ServerRequestInterface $request) use ($loop, $chat) { +$server = new Server(function (ServerRequestInterface $request) use ($chat) { if ($request->getHeaderLine('Upgrade') !== 'chat' || $request->getProtocolVersion() === '1.0') { return new Response( 426, @@ -68,7 +66,7 @@ }); // say hello to new user - $loop->addTimer(0, function () use ($chat, $username, $out) { + Loop::addTimer(0, function () use ($chat, $username, $out) { $out->write('Welcome to this chat example, ' . $username . '!' . PHP_EOL); $chat->write($username . ' joined' . PHP_EOL); }); @@ -87,9 +85,7 @@ ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/examples/91-client-benchmark-download.php b/examples/91-client-benchmark-download.php index 4fd39b9d..2f76a3f3 100644 --- a/examples/91-client-benchmark-download.php +++ b/examples/91-client-benchmark-download.php @@ -11,8 +11,9 @@ // b2) run HTTP client receiving a 10 GB download: // $ php examples/91-client-benchmark-download.php http://localhost:8080/10g.bin -use React\Http\Browser; use Psr\Http\Message\ResponseInterface; +use React\EventLoop\Loop; +use React\Http\Browser; use React\Stream\ReadableStreamInterface; $url = isset($argv[1]) ? $argv[1] : 'http://google.com/'; @@ -23,12 +24,11 @@ echo 'NOTICE: The "xdebug" extension is loaded, this has a major impact on performance.' . PHP_EOL; } -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); echo 'Requesting ' . $url . '…' . PHP_EOL; -$client->requestStreaming('GET', $url)->then(function (ResponseInterface $response) use ($loop) { +$client->requestStreaming('GET', $url)->then(function (ResponseInterface $response) { echo 'Headers received' . PHP_EOL; echo RingCentral\Psr7\str($response); @@ -42,19 +42,17 @@ }); // report progress every 0.1s - $timer = $loop->addPeriodicTimer(0.1, function () use (&$bytes) { + $timer = Loop::addPeriodicTimer(0.1, function () use (&$bytes) { echo "\rDownloaded " . $bytes . " bytes…"; }); // report results once the stream closes $time = microtime(true); - $stream->on('close', function() use (&$bytes, $timer, $loop, $time) { - $loop->cancelTimer($timer); + $stream->on('close', function() use (&$bytes, $timer, $time) { + Loop::cancelTimer($timer); $time = microtime(true) - $time; echo "\r" . 'Downloaded ' . $bytes . ' bytes in ' . round($time, 3) . 's => ' . round($bytes / $time / 1000000, 1) . ' MB/s' . PHP_EOL; }); }, 'printf'); - -$loop->run(); diff --git a/examples/92-client-benchmark-upload.php b/examples/92-client-benchmark-upload.php index cc2cf0c0..bd767966 100644 --- a/examples/92-client-benchmark-upload.php +++ b/examples/92-client-benchmark-upload.php @@ -11,9 +11,10 @@ // b2) run HTTP client sending a 10 GB upload // $ php examples/92-client-benchmark-upload.php http://localhost:8080/ 10000 -use React\Http\Browser; use Evenement\EventEmitter; use Psr\Http\Message\ResponseInterface; +use React\EventLoop\Loop; +use React\Http\Browser; use React\Stream\ReadableStreamInterface; use React\Stream\Util; use React\Stream\WritableStreamInterface; @@ -92,33 +93,30 @@ public function getPosition() } } -$loop = React\EventLoop\Factory::create(); -$client = new Browser($loop); +$client = new Browser(); $url = isset($argv[1]) ? $argv[1] : 'http://httpbin.org/post'; $n = isset($argv[2]) ? $argv[2] : 10; $source = new ChunkRepeater(str_repeat('x', 1000000), $n); -$loop->futureTick(function () use ($source) { +Loop::futureTick(function () use ($source) { $source->resume(); }); echo 'POSTing ' . $n . ' MB to ' . $url . PHP_EOL; $start = microtime(true); -$report = $loop->addPeriodicTimer(0.05, function () use ($source, $start) { +$report = Loop::addPeriodicTimer(0.05, function () use ($source, $start) { printf("\r%d bytes in %0.3fs...", $source->getPosition(), microtime(true) - $start); }); -$client->post($url, array('Content-Length' => $n * 1000000), $source)->then(function (ResponseInterface $response) use ($source, $report, $loop, $start) { +$client->post($url, array('Content-Length' => $n * 1000000), $source)->then(function (ResponseInterface $response) use ($source, $report, $start) { $now = microtime(true); - $loop->cancelTimer($report); + Loop::cancelTimer($report); printf("\r%d bytes in %0.3fs => %.1f MB/s\n", $source->getPosition(), $now - $start, $source->getPosition() / ($now - $start) / 1000000); echo rtrim(preg_replace('/x{5,}/','x…', (string) $response->getBody()), PHP_EOL) . PHP_EOL; -}, function ($e) use ($loop, $report) { - $loop->cancelTimer($report); +}, function ($e) use ($report) { + Loop::cancelTimer($report); echo 'Error: ' . $e->getMessage() . PHP_EOL; }); - -$loop->run(); diff --git a/examples/99-server-benchmark-download.php b/examples/99-server-benchmark-download.php index 1a49df72..a6b4e9c1 100644 --- a/examples/99-server-benchmark-download.php +++ b/examples/99-server-benchmark-download.php @@ -16,7 +16,6 @@ use Evenement\EventEmitter; use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\Factory; use React\Http\Message\Response; use React\Http\Server; use React\Stream\ReadableStreamInterface; @@ -24,8 +23,6 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = Factory::create(); - /** A readable stream that can emit a lot of data */ class ChunkRepeater extends EventEmitter implements ReadableStreamInterface { @@ -94,7 +91,7 @@ public function getSize() } } -$server = new Server($loop, function (ServerRequestInterface $request) use ($loop) { +$server = new Server(function (ServerRequestInterface $request) { switch ($request->getUri()->getPath()) { case '/': return new Response( @@ -114,7 +111,7 @@ public function getSize() return new Response(404); } - $loop->addTimer(0, array($stream, 'resume')); + React\EventLoop\Loop::addTimer(0, array($stream, 'resume')); return new Response( 200, @@ -126,9 +123,7 @@ public function getSize() ); }); -$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop); +$socket = new \React\Socket\Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0'); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; - -$loop->run(); diff --git a/src/Browser.php b/src/Browser.php index 188320e8..ed83689b 100644 --- a/src/Browser.php +++ b/src/Browser.php @@ -5,6 +5,7 @@ use Psr\Http\Message\ResponseInterface; use RingCentral\Psr7\Request; use RingCentral\Psr7\Uri; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Http\Io\ReadableBodyStream; use React\Http\Io\Sender; @@ -26,20 +27,23 @@ class Browser /** * The `Browser` is responsible for sending HTTP requests to your HTTP server * and keeps track of pending incoming HTTP responses. - * It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage). * * ```php - * $loop = React\EventLoop\Factory::create(); - * - * $browser = new React\Http\Browser($loop); + * $browser = new React\Http\Browser(); * ``` * + * This class takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use for this object. You can use a `null` value + * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). + * This value SHOULD NOT be given unless you're sure you want to explicitly use a + * given event loop instance. + * * If you need custom connector settings (DNS resolution, TLS parameters, timeouts, * proxy servers etc.), you can explicitly pass a custom instance of the * [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): * * ```php - * $connector = new React\Socket\Connector($loop, array( + * $connector = new React\Socket\Connector(null, array( * 'dns' => '127.0.0.1', * 'tcp' => array( * 'bindto' => '192.168.10.1:0' @@ -50,15 +54,16 @@ class Browser * ) * )); * - * $browser = new React\Http\Browser($loop, $connector); + * $browser = new React\Http\Browser(null, $connector); * ``` * - * @param LoopInterface $loop - * @param ConnectorInterface|null $connector [optional] Connector to use. + * @param ?LoopInterface $loop + * @param ?ConnectorInterface $connector [optional] Connector to use. * Should be `null` in order to use default Connector. */ - public function __construct(LoopInterface $loop, ConnectorInterface $connector = null) + public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null) { + $loop = $loop ?: Loop::get(); $this->transaction = new Transaction( Sender::createFromLoop($loop, $connector), $loop @@ -127,7 +132,7 @@ public function get($url, array $headers = array()) * * ```php * $body = new React\Stream\ThroughStream(); - * $loop->addTimer(1.0, function () use ($body) { + * Loop::addTimer(1.0, function () use ($body) { * $body->end("hello world"); * }); * @@ -185,7 +190,7 @@ public function head($url, array $headers = array()) * * ```php * $body = new React\Stream\ThroughStream(); - * $loop->addTimer(1.0, function () use ($body) { + * Loop::addTimer(1.0, function () use ($body) { * $body->end("hello world"); * }); * @@ -227,7 +232,7 @@ public function patch($url, array $headers = array(), $contents = '') * * ```php * $body = new React\Stream\ThroughStream(); - * $loop->addTimer(1.0, function () use ($body) { + * Loop::addTimer(1.0, function () use ($body) { * $body->end("hello world"); * }); * @@ -291,7 +296,7 @@ public function delete($url, array $headers = array(), $contents = '') * * ```php * $body = new React\Stream\ThroughStream(); - * $loop->addTimer(1.0, function () use ($body) { + * Loop::addTimer(1.0, function () use ($body) { * $body->end("hello world"); * }); * @@ -362,7 +367,7 @@ public function request($method, $url, array $headers = array(), $body = '') * * ```php * $body = new React\Stream\ThroughStream(); - * $loop->addTimer(1.0, function () use ($body) { + * Loop::addTimer(1.0, function () use ($body) { * $body->end("hello world"); * }); * diff --git a/src/Middleware/LimitConcurrentRequestsMiddleware.php b/src/Middleware/LimitConcurrentRequestsMiddleware.php index 9aaf5ff2..cc1dfc42 100644 --- a/src/Middleware/LimitConcurrentRequestsMiddleware.php +++ b/src/Middleware/LimitConcurrentRequestsMiddleware.php @@ -30,7 +30,6 @@ * * ```php * $server = new React\Http\Server( - * $loop, * new React\Http\Middleware\StreamingRequestMiddleware(), * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(10), * $handler @@ -43,7 +42,6 @@ * * ```php * $server = new React\Http\Server( - * $loop, * new React\Http\Middleware\StreamingRequestMiddleware(), * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers * new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request @@ -58,7 +56,6 @@ * * ```php * $server = new React\Http\Server( - * $loop, * new React\Http\Middleware\StreamingRequestMiddleware(), * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers * new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request diff --git a/src/Server.php b/src/Server.php index 1aa5d405..c2e3f5a6 100644 --- a/src/Server.php +++ b/src/Server.php @@ -3,6 +3,7 @@ namespace React\Http; use Evenement\EventEmitter; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Http\Io\IniUtil; use React\Http\Io\MiddlewareRunner; @@ -23,7 +24,7 @@ * object and expects a [response](#server-response) object in return: * * ```php - * $server = new React\Http\Server($loop, function (Psr\Http\Message\ServerRequestInterface $request) { + * $server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) { * return new React\Http\Message\Response( * 200, * array( @@ -42,6 +43,12 @@ * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface), * see also following [response](#server-response) chapter for more details. * + * This class takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use for this object. You can use a `null` value + * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). + * This value SHOULD NOT be given unless you're sure you want to explicitly use a + * given event loop instance. + * * In order to start listening for any incoming connections, the `Server` needs * to be attached to an instance of * [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface) @@ -51,9 +58,9 @@ * to start a plaintext HTTP server like this: * * ```php - * $server = new React\Http\Server($loop, $handler); + * $server = new React\Http\Server($handler); * - * $socket = new React\Socket\Server('0.0.0.0:8080', $loop); + * $socket = new React\Socket\Server('0.0.0.0:8080'); * $server->listen($socket); * ``` * @@ -122,7 +129,6 @@ * * ```php * $server = new React\Http\Server( - * $loop, * new React\Http\Middleware\StreamingRequestMiddleware(), * new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers * new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request @@ -148,7 +154,6 @@ * * ```php * $server = new React\Http\Server( - * $loop, * new React\Http\Middleware\StreamingRequestMiddleware(), * $handler * ); @@ -191,14 +196,19 @@ final class Server extends EventEmitter * connections in order to then parse incoming data as HTTP. * See also [listen()](#listen) for more details. * - * @param LoopInterface $loop + * @param callable|LoopInterface $requestHandlerOrLoop * @param callable[] ...$requestHandler * @see self::listen() */ - public function __construct(LoopInterface $loop) + public function __construct($requestHandlerOrLoop) { $requestHandlers = \func_get_args(); - \array_shift($requestHandlers); + if (reset($requestHandlers) instanceof LoopInterface) { + $loop = \array_shift($requestHandlers); + } else { + $loop = Loop::get(); + } + $requestHandlersCount = \count($requestHandlers); if ($requestHandlersCount === 0 || \count(\array_filter($requestHandlers, 'is_callable')) < $requestHandlersCount) { throw new \InvalidArgumentException('Invalid request handler given'); @@ -253,9 +263,9 @@ public function __construct(LoopInterface $loop) * order to start a plaintext HTTP server like this: * * ```php - * $server = new React\Http\Server($loop, $handler); + * $server = new React\Http\Server($handler); * - * $socket = new React\Socket\Server(8080, $loop); + * $socket = new React\Socket\Server(8080); * $server->listen($socket); * ``` * @@ -279,9 +289,9 @@ public function __construct(LoopInterface $loop) * `passphrase` like this: * * ```php - * $server = new React\Http\Server($loop, $handler); + * $server = new React\Http\Server($handler); * - * $socket = new React\Socket\Server('tls://0.0.0.0:8443', $loop, array( + * $socket = new React\Socket\Server('tls://0.0.0.0:8443', null, array( * 'local_cert' => __DIR__ . '/localhost.pem' * )); * $server->listen($socket); diff --git a/tests/BrowserTest.php b/tests/BrowserTest.php index 612875fc..5df2b837 100644 --- a/tests/BrowserTest.php +++ b/tests/BrowserTest.php @@ -28,6 +28,21 @@ public function setUpBrowser() $ref->setValue($this->browser, $this->sender); } + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $browser = new Browser(); + + $ref = new \ReflectionProperty($browser, 'transaction'); + $ref->setAccessible(true); + $transaction = $ref->getValue($browser); + + $ref = new \ReflectionProperty($transaction, 'loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($transaction); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + public function testGetSendsGetRequest() { $that = $this; diff --git a/tests/Client/FunctionalIntegrationTest.php b/tests/Client/FunctionalIntegrationTest.php index 2db75b35..3e07803a 100644 --- a/tests/Client/FunctionalIntegrationTest.php +++ b/tests/Client/FunctionalIntegrationTest.php @@ -83,6 +83,9 @@ public function testRequestLegacyHttpServerWithOnlyLineFeedReturnsSuccessfulResp /** @group internet */ public function testSuccessfulResponseEmitsEnd() { + // max_nesting_level was set to 100 for PHP Versions < 5.4 which resulted in failing test for legacy PHP + ini_set('xdebug.max_nesting_level', 256); + $loop = Factory::create(); $client = new Client($loop); @@ -106,6 +109,9 @@ public function testPostDataReturnsData() $this->markTestSkipped('Not supported on HHVM'); } + // max_nesting_level was set to 100 for PHP Versions < 5.4 which resulted in failing test for legacy PHP + ini_set('xdebug.max_nesting_level', 256); + $loop = Factory::create(); $client = new Client($loop); diff --git a/tests/ServerTest.php b/tests/ServerTest.php index ff2cd9c1..6cb1b9b5 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -46,6 +46,21 @@ public function setUpConnectionMockAndSocket() $this->socket = new SocketServerStub(); } + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $server = new Server(function () { }); + + $ref = new \ReflectionProperty($server, 'streamingServer'); + $ref->setAccessible(true); + $streamingServer = $ref->getValue($server); + + $ref = new \ReflectionProperty($streamingServer, 'loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($streamingServer); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + public function testInvalidCallbackFunctionLeadsToException() { $this->setExpectedException('InvalidArgumentException');