From 26e6a51730f8d27f772de60d5667dfd2f56ceffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 12 Jun 2021 12:47:58 +0200 Subject: [PATCH 1/2] Simplify `App` usage by making `LoopInterface` argument optional --- composer.json | 1 + examples/index.php | 8 +- src/App.php | 8 +- tests/AppMiddlewareTest.php | 56 ++++---------- tests/AppTest.php | 149 ++++++++++++++++++------------------ 5 files changed, 103 insertions(+), 119 deletions(-) diff --git a/composer.json b/composer.json index 83113af..7523054 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "require": { "php": ">=7.1", "nikic/fast-route": "^1.3", + "react/event-loop": "dev-master#1a709e2 as 1.2.0", "react/http": "^1.1", "react/promise": "^2.7" }, diff --git a/examples/index.php b/examples/index.php index 072a6e5..ae377a6 100644 --- a/examples/index.php +++ b/examples/index.php @@ -1,13 +1,11 @@ get('/', function () { return new React\Http\Message\Response( @@ -73,9 +71,10 @@ ); }); -$app->get('/stream', function (ServerRequestInterface $request) use ($loop) { +$app->get('/stream', function (ServerRequestInterface $request) { $stream = new ThroughStream(); + $loop = React\EventLoop\Loop::get(); $timer = $loop->addPeriodicTimer(0.5, function () use ($stream) { $stream->write(microtime(true) . ' hi!' . PHP_EOL); }); @@ -137,4 +136,3 @@ }); $app->run(); -$loop->run(); diff --git a/src/App.php b/src/App.php index 225901f..b48fb44 100644 --- a/src/App.php +++ b/src/App.php @@ -8,6 +8,7 @@ use FastRoute\RouteParser\Std as RouteParser; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Http\Server as HttpServer; use React\Http\Message\Response; @@ -23,8 +24,11 @@ class App private $router; private $routeDispatcher; - public function __construct(LoopInterface $loop) + public function __construct(LoopInterface $loop = null) { + if ($loop === null) { + $loop = Loop::get(); + } $this->loop = $loop; $this->router = new RouteCollector(new RouteParser(), new RouteGenerator()); } @@ -153,6 +157,8 @@ public function run() } else { $this->runOnce(); } + + $this->loop->run(); } private function runLoop() diff --git a/tests/AppMiddlewareTest.php b/tests/AppMiddlewareTest.php index 087245d..0302aa7 100644 --- a/tests/AppMiddlewareTest.php +++ b/tests/AppMiddlewareTest.php @@ -8,7 +8,6 @@ use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use React\EventLoop\LoopInterface; use React\Http\Message\ServerRequest; use React\Http\Message\Response; use React\Promise\PromiseInterface; @@ -18,8 +17,7 @@ class AppMiddlewareTest extends TestCase { public function testGetMethodWithMiddlewareAddsGetRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -36,8 +34,7 @@ public function testGetMethodWithMiddlewareAddsGetRouteOnRouter() public function testHeadMethodWithMiddlewareAddsHeadRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -54,8 +51,7 @@ public function testHeadMethodWithMiddlewareAddsHeadRouteOnRouter() public function testPostMethodWithMiddlewareAddsPostRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -72,8 +68,7 @@ public function testPostMethodWithMiddlewareAddsPostRouteOnRouter() public function testPutMethodWithMiddlewareAddsPutRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -90,8 +85,7 @@ public function testPutMethodWithMiddlewareAddsPutRouteOnRouter() public function testPatchMethodWithMiddlewareAddsPatchRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -108,8 +102,7 @@ public function testPatchMethodWithMiddlewareAddsPatchRouteOnRouter() public function testDeleteMethodWithMiddlewareAddsDeleteRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -126,8 +119,7 @@ public function testDeleteMethodWithMiddlewareAddsDeleteRouteOnRouter() public function testOptionsMethodWithMiddlewareAddsOptionsRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -144,8 +136,7 @@ public function testOptionsMethodWithMiddlewareAddsOptionsRouteOnRouter() public function testAnyMethodWithMiddlewareAddsAllHttpMethodsOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -162,8 +153,7 @@ public function testAnyMethodWithMiddlewareAddsAllHttpMethodsOnRouter() public function testMapMethodWithMiddlewareAddsGivenMethodsOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $middleware = function () {}; $controller = function () { }; @@ -180,9 +170,7 @@ public function testMapMethodWithMiddlewareAddsGivenMethodsOnRouter() public function testMiddlewareCallsNextReturnsResponseFromRouter() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { return $next($request); @@ -216,9 +204,7 @@ public function testMiddlewareCallsNextReturnsResponseFromRouter() public function testMiddlewareCallsNextWithModifiedRequestReturnsResponseFromRouter() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { return $next($request->withAttribute('name', 'Alice')); @@ -252,9 +238,7 @@ public function testMiddlewareCallsNextWithModifiedRequestReturnsResponseFromRou public function testMiddlewareCallsNextReturnsResponseModifiedInMiddlewareFromRouter() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { $response = $next($request); @@ -289,9 +273,7 @@ public function testMiddlewareCallsNextReturnsResponseModifiedInMiddlewareFromRo public function testMiddlewareCallsNextReturnsDeferredResponseModifiedInMiddlewareFromRouter() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { $promise = $next($request); @@ -336,9 +318,7 @@ public function testMiddlewareCallsNextReturnsDeferredResponseModifiedInMiddlewa public function testMiddlewareCallsNextReturnsCoroutineResponseModifiedInMiddlewareFromRouter() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { $generator = $next($request); @@ -385,9 +365,7 @@ public function testMiddlewareCallsNextReturnsCoroutineResponseModifiedInMiddlew public function testMiddlewareCallsNextWhichThrowsExceptionReturnsInternalServerErrorResponse() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $middleware = function (ServerRequestInterface $request, callable $next) { return $next($request); @@ -416,9 +394,7 @@ public function testMiddlewareCallsNextWhichThrowsExceptionReturnsInternalServer public function testMiddlewareWhichThrowsExceptionReturnsInternalServerErrorResponse() { - $loop = $this->createMock(LoopInterface::class); - - $app = new App($loop); + $app = new App(); $line = __LINE__ + 2; $middleware = function (ServerRequestInterface $request, callable $next) { diff --git a/tests/AppTest.php b/tests/AppTest.php index 0831137..cf0b380 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Http\Message\Response; use React\Http\Message\ServerRequest; @@ -17,11 +18,49 @@ class AppTest extends TestCase { - public function testGetMethodAddsGetRouteOnRouter() + public function testConstructWithLoopAssignsGivenLoopInstance() + { + $loop = $this->createMock(LoopInterface::class); + $app = new App($loop); + + $ref = new ReflectionProperty($app, 'loop'); + $ref->setAccessible(true); + $ret = $ref->getValue($app); + + $this->assertSame($loop, $ret); + } + + public function testConstructWithoutLoopAssignsGlobalLoopInstance() + { + $app = new App(); + + $ref = new ReflectionProperty($app, 'loop'); + $ref->setAccessible(true); + $ret = $ref->getValue($app); + + $this->assertSame(Loop::get(), $ret); + } + + public function testRunWillRunGivenLoopInstanceAndReportListeningAddress() { + $socket = @stream_socket_server('127.0.0.1:8080'); + if ($socket === false) { + $this->markTestSkipped('Listen address :8080 already in use'); + } + fclose($socket); + $loop = $this->createMock(LoopInterface::class); + $loop->expects($this->once())->method('run'); $app = new App($loop); + $this->expectOutputRegex('/' . preg_quote('Listening on tcp://127.0.0.1:8080' . PHP_EOL, '/') . '$/'); + $app->run(); + } + + public function testGetMethodAddsGetRouteOnRouter() + { + $app = new App(); + $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['GET'], '/', $this->anything()); @@ -34,8 +73,7 @@ public function testGetMethodAddsGetRouteOnRouter() public function testHeadMethodAddsHeadRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['HEAD'], '/', $this->anything()); @@ -49,8 +87,7 @@ public function testHeadMethodAddsHeadRouteOnRouter() public function testPostMethodAddsPostRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['POST'], '/', $this->anything()); @@ -64,8 +101,7 @@ public function testPostMethodAddsPostRouteOnRouter() public function testPutMethodAddsPutRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['PUT'], '/', $this->anything()); @@ -79,8 +115,7 @@ public function testPutMethodAddsPutRouteOnRouter() public function testPatchMethodAddsPatchRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['PATCH'], '/', $this->anything()); @@ -94,8 +129,7 @@ public function testPatchMethodAddsPatchRouteOnRouter() public function testDeleteMethodAddsDeleteRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['DELETE'], '/', $this->anything()); @@ -109,8 +143,7 @@ public function testDeleteMethodAddsDeleteRouteOnRouter() public function testOptionsMethodAddsOptionsRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['OPTIONS'], '/', $this->anything()); @@ -124,8 +157,7 @@ public function testOptionsMethodAddsOptionsRouteOnRouter() public function testAnyMethodAddsRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], '/', $this->anything()); @@ -139,8 +171,7 @@ public function testAnyMethodAddsRouteOnRouter() public function testMapMethodAddsRouteOnRouter() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $router = $this->createMock(RouteCollector::class); $router->expects($this->once())->method('addRoute')->with(['GET', 'POST'], '/', $this->anything()); @@ -154,8 +185,7 @@ public function testMapMethodAddsRouteOnRouter() public function testRedirectMethodAddsGetRouteOnRouterWhichWhenInvokedReturnsRedirectResponseWithTargetLocation() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $handler = null; $router = $this->createMock(RouteCollector::class); @@ -184,8 +214,7 @@ public function testRedirectMethodAddsGetRouteOnRouterWhichWhenInvokedReturnsRed public function testRedirectMethodWithCustomRedirectCodeAddsGetRouteOnRouterWhichWhenInvokedReturnsRedirectResponseWithCustomRedirectCode() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $handler = null; $router = $this->createMock(RouteCollector::class); @@ -214,8 +243,7 @@ public function testRedirectMethodWithCustomRedirectCodeAddsGetRouteOnRouterWhic public function testRequestFromGlobalsWithNoServerVariablesDefaultsToGetRequestToLocalhost() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); // $request = $app->requestFromGlobals(); $ref = new ReflectionMethod($app, 'requestFromGlobals'); @@ -235,8 +263,7 @@ public function testRequestFromGlobalsWithNoServerVariablesDefaultsToGetRequestT */ public function testRequestFromGlobalsWithHeadRequest() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $_SERVER['REQUEST_METHOD'] = 'HEAD'; $_SERVER['REQUEST_URI'] = '//'; @@ -261,8 +288,7 @@ public function testRequestFromGlobalsWithHeadRequest() */ public function testRequestFromGlobalsWithGetRequestOverCustomPort() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['REQUEST_URI'] = '/path'; @@ -287,8 +313,7 @@ public function testRequestFromGlobalsWithGetRequestOverCustomPort() */ public function testRequestFromGlobalsWithGetRequestOverHttps() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['REQUEST_URI'] = '/'; @@ -311,8 +336,7 @@ public function testRequestFromGlobalsWithGetRequestOverHttps() public function testHandleRequestWithProxyRequestReturnsResponseWithMessageThatProxyRequestAreNotAllowed() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $request = new ServerRequest('GET', 'http://google.com/'); $request = $request->withRequestTarget('http://google.com/'); @@ -331,8 +355,7 @@ public function testHandleRequestWithProxyRequestReturnsResponseWithMessageThatP public function testHandleRequestWithUnknownRouteReturnsResponseWithFileNotFoundMessage() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $request = new ServerRequest('GET', 'http://localhost/invalid'); @@ -350,8 +373,7 @@ public function testHandleRequestWithUnknownRouteReturnsResponseWithFileNotFound public function testHandleRequestWithInvalidRequestMethodReturnsResponseWithMethodNotAllowedMessage() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { }); $app->post('/users', function () { }); @@ -373,8 +395,7 @@ public function testHandleRequestWithInvalidRequestMethodReturnsResponseWithMeth public function testHandleRequestWithMatchingRouteReturnsResponseFromMatchingRouteHandler() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { return new Response( @@ -402,8 +423,7 @@ public function testHandleRequestWithMatchingRouteReturnsResponseFromMatchingRou public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithResponseWhenHandlerReturnsPromiseWhichFulfillsWithResponse() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { return \React\Promise\resolve(new Response( @@ -439,8 +459,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPendingPromiseWhenHandlerReturnsPendingPromise() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { return new Promise(function () { }); @@ -468,8 +487,7 @@ public function testHandleRequestWithMatchingRouteReturnsPendingPromiseWhenHandl public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithResponseWhenHandlerReturnsCoroutineWhichReturnsResponseAfterYieldingResolvedPromise() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { $body = yield \React\Promise\resolve("OK\n"); @@ -507,8 +525,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithResponseWhenHandlerReturnsCoroutineWhichReturnsResponseAfterCatchingExceptionFromYieldingRejectedPromise() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { $body = ''; @@ -551,8 +568,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPendingPromiseWhenHandlerReturnsCoroutineThatYieldsPendingPromise() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { yield new Promise(function () { }); @@ -580,8 +596,7 @@ public function testHandleRequestWithMatchingRouteReturnsPendingPromiseWhenHandl public function testHandleRequestWithMatchingRouteAndRouteVariablesReturnsResponseFromHandlerWithRouteVariablesAssignedAsRequestAttributes() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users/{name}', function (ServerRequestInterface $request) { $name = $request->getAttribute('name'); @@ -611,8 +626,7 @@ public function testHandleRequestWithMatchingRouteAndRouteVariablesReturnsRespon public function testHandleRequestWithMatchingRouteReturnsInternalServerErrorResponseWhenHandlerThrowsException() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $line = __LINE__ + 2; $app->get('/users', function () { @@ -635,8 +649,7 @@ public function testHandleRequestWithMatchingRouteReturnsInternalServerErrorResp public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsPromiseWhichRejectsWithException() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $line = __LINE__ + 2; $app->get('/users', function () { @@ -667,8 +680,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsPromiseWhichRejectsWithNull() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { return \React\Promise\reject(null); @@ -698,8 +710,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsCoroutineWhichYieldsRejectedPromise() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $line = __LINE__ + 2; $app->get('/users', function () { @@ -730,8 +741,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsCoroutineWhichThrowsExceptionAfterYielding() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $line = __LINE__ + 3; $app->get('/users', function () { @@ -763,8 +773,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsCoroutineWhichReturnsNull() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { $value = yield \React\Promise\resolve(null); @@ -795,8 +804,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsCoroutineWhichYieldsNull() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () { yield null; @@ -869,8 +877,7 @@ public function provideInvalidReturnValue() */ public function testHandleRequestWithMatchingRouteReturnsInternalServerErrorResponseWhenHandlerReturnsWrongValue($value, $name) { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () use ($value) { return $value; @@ -897,8 +904,7 @@ public function testHandleRequestWithMatchingRouteReturnsInternalServerErrorResp */ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWithInternalServerErrorResponseWhenHandlerReturnsPromiseWhichFulfillsWithWrongValue($value, $name) { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); $app->get('/users', function () use ($value) { return \React\Promise\resolve($value); @@ -928,8 +934,7 @@ public function testHandleRequestWithMatchingRouteReturnsPromiseWhichFulfillsWit public function testLogRequestResponsePrintsRequestLogWithCurrentDateAndTime() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); // 2021-01-29 12:22:01.717 127.0.0.1 "GET /users HTTP/1.1" 200 6\n $this->expectOutputRegex("/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} 127\.0\.0\.1 \"GET \/users HTTP\/1\.1\" 200 6\n$/"); @@ -945,8 +950,7 @@ public function testLogRequestResponsePrintsRequestLogWithCurrentDateAndTime() public function testLogRequestResponseWithoutRemoteAddressPrintsRequestLogWithDashAsPlaceholder() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); // 2021-01-29 12:22:01.717 - "GET /users HTTP/1.1" 200 6\n $this->expectOutputRegex("/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} - \"GET \/users HTTP\/1\.1\" 200 6\n$/"); @@ -962,8 +966,7 @@ public function testLogRequestResponseWithoutRemoteAddressPrintsRequestLogWithDa public function testLogPrintsMessageWithCurrentDateAndTime() { - $loop = $this->createMock(LoopInterface::class); - $app = new App($loop); + $app = new App(); // 2021-01-29 12:22:01.717 Hello\n $this->expectOutputRegex("/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} Hello\n$/"); From 74dcc40b7ef6995411721bc91495f8a01a171528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sun, 13 Jun 2021 17:29:07 +0200 Subject: [PATCH 2/2] Simplify documentation by omitting optional `LoopInterface` argument --- README.md | 4 +--- docs/api/app.md | 25 +------------------------ docs/api/middleware.md | 4 +--- docs/best-practices/controllers.md | 8 ++------ docs/getting-started/quickstart.md | 4 +--- 5 files changed, 6 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index f84ec5e..7e73347 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,7 @@ empty project directory: require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$app = new FrameworkX\App($loop); +$app = new FrameworkX\App(); $app->get('/', function () { return new React\Http\Message\Response( @@ -41,7 +40,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re }); $app->run(); -$loop->run(); ``` Next, we need to install X and its dependencies to actually run this project. diff --git a/docs/api/app.md b/docs/api/app.md index 81be014..f881269 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -3,42 +3,19 @@ The `App` class is your main entrypoint to any application that builds on top of X. It provides a simple API for routing HTTP requests as commonly used in RESTful applications. -Internally, the `App` object builds on top of [ReactPHP](https://reactphp.org/) -to do its magic, hence you have to create it like this: - ```php # app.php run(); -$loop->run(); ``` -> ℹ️ **Heads up!** -> -> Major improvements upcoming! We're actively contributing to our underlying -> libraries to make sure this can look like this in the near future: -> -> ```php -> # app.php -> -> require __DIR__ . '/vendor/autoload.php'; -> -> $app = new FrameworkX\App(); -> -> // Register routes here, see routing… -> -> $app->run(); -> ``` - ## Routing The `App` class offers a number of API methods that allow you to route incoming diff --git a/docs/api/middleware.md b/docs/api/middleware.md index bebad5c..fc44b58 100644 --- a/docs/api/middleware.md +++ b/docs/api/middleware.md @@ -257,13 +257,11 @@ a global middleware handler for all registered routes: use Acme\Todo\AdminMiddleware; use Acme\Todo\UserController; -$loop = React\EventLoop\Factory::create(); -$app = new FrameworkX\App($loop, new AdminMiddleware()); +$app = new FrameworkX\App(new AdminMiddleware()); $app->get('/user', new UserController()); $app->run(); -$loop->run(); ``` You can also combine global middleware handlers (think logging) with additional diff --git a/docs/best-practices/controllers.md b/docs/best-practices/controllers.md index c0bf2ae..a55ac63 100644 --- a/docs/best-practices/controllers.md +++ b/docs/best-practices/controllers.md @@ -13,8 +13,7 @@ To get started, let's take a look at the following simple closure definitions: require __DIR__ . '/vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$app = new FrameworkX\App($loop); +$app = new FrameworkX\App(); $app->get('/', function () { return new React\Http\Message\Response( @@ -33,7 +32,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re }); $app->run(); -$loop->run(); ``` While easy to get started, it's also easy to see how this will get out of hand for more complex @@ -49,14 +47,12 @@ definition into three even simpler files: require __DIR__ . '/vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$app = new FrameworkX\App($loop); +$app = new FrameworkX\App(); $app->get('/', new Acme\Todo\HelloController()); $app->get('/users/{name}', new Acme\Todo\UserController()); $app->run(); -$loop->run(); ``` ```php diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index 53faa1c..0039003 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -22,8 +22,7 @@ You can use this example to get started by creating a new `app.php` file in your require __DIR__ . '/vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$app = new FrameworkX\App($loop); +$app = new FrameworkX\App(); $app->get('/', function () { return new React\Http\Message\Response( @@ -42,7 +41,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re }); $app->run(); -$loop->run(); ``` On a code level, this is everything you need to get started.