diff --git a/flight/Engine.php b/flight/Engine.php index aa4e202..c325394 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -94,6 +94,9 @@ class Engine /** If the framework has been initialized or not. */ protected bool $initialized = false; + /** If the request has been handled or not. */ + protected bool $requestHandled = false; + public function __construct() { $this->loader = new Loader(); @@ -476,6 +479,19 @@ class Engine { $dispatched = false; $self = $this; + + // This behavior is specifically for test suites, and for async platforms like swoole, workerman, etc. + if ($this->requestHandled === false) { + // not doing much here, just setting the requestHandled flag to true + $this->requestHandled = true; + } else { + // deregister the request and response objects and re-register them with new instances + $this->unregister('request'); + $this->unregister('response'); + $this->register('request', Request::class); + $this->register('response', Response::class); + $this->router()->reset(); + } $request = $this->request(); $response = $this->response(); $router = $this->router(); @@ -498,7 +514,6 @@ class Engine // Route the request $failedMiddlewareCheck = false; - while ($route = $router->route($request)) { $params = array_values($route->params); diff --git a/flight/net/Request.php b/flight/net/Request.php index f88c770..5164b11 100644 --- a/flight/net/Request.php +++ b/flight/net/Request.php @@ -211,8 +211,8 @@ class Request $this->data->setData($data); } } - // Check PUT, PATCH, DELETE for application/x-www-form-urlencoded data - } else if (in_array($this->method, [ 'PUT', 'DELETE', 'PATCH' ], true) === true) { + // Check PUT, PATCH, DELETE for application/x-www-form-urlencoded data + } elseif (in_array($this->method, [ 'PUT', 'DELETE', 'PATCH' ], true) === true) { $body = $this->getBody(); if ($body !== '') { $data = []; diff --git a/tests/EngineTest.php b/tests/EngineTest.php index 45445ed..fc2e8ff 100644 --- a/tests/EngineTest.php +++ b/tests/EngineTest.php @@ -175,6 +175,30 @@ class EngineTest extends TestCase $engine->start(); } + public function testDoubleStart() + { + $engine = new Engine(); + $engine->route('/someRoute', function () { + echo 'i ran'; + }, true); + $engine->request()->url = '/someRoute'; + $engine->start(); + + $request = $engine->request(); + $response = $engine->response(); + + // This is pretending like this is embodied in a platform like swoole where + // another request comes in while still holding all the same state. + $_SERVER['REQUEST_METHOD'] = 'GET'; + $_SERVER['REQUEST_URI'] = '/someRoute'; + $engine->start(); + + $this->assertFalse($request === $engine->request()); + $this->assertFalse($response === $engine->response()); + + $this->expectOutputString('i rani ran'); + } + public function testStopWithCode() { $engine = new class extends Engine { diff --git a/tests/FlightAsyncTest.php b/tests/FlightAsyncTest.php new file mode 100644 index 0000000..1a53f44 --- /dev/null +++ b/tests/FlightAsyncTest.php @@ -0,0 +1,83 @@ +expectOutputString('hello world'); + Flight::start(); + } + + public function testMultipleRoutes() + { + Flight::route('GET /', function () { + echo 'hello world'; + }); + + Flight::route('GET /test', function () { + echo 'test'; + }); + + $this->expectOutputString('test'); + $_SERVER['REQUEST_URI'] = '/test'; + Flight::start(); + } + + public function testMultipleStartsSingleRoute() + { + Flight::route('GET /', function () { + echo 'hello world'; + }); + + $this->expectOutputString('hello worldhello world'); + Flight::start(); + Flight::start(); + } + + public function testMultipleStartsMultipleRoutes() + { + Flight::route('GET /', function () { + echo 'hello world'; + }); + + Flight::route('GET /test', function () { + echo 'test'; + }); + + $this->expectOutputString('testhello world'); + $_SERVER['REQUEST_URI'] = '/test'; + Flight::start(); + $_SERVER['REQUEST_URI'] = '/'; + Flight::start(); + } +} diff --git a/tests/FlightTest.php b/tests/FlightTest.php index 54acf53..fbc8eb6 100644 --- a/tests/FlightTest.php +++ b/tests/FlightTest.php @@ -378,7 +378,7 @@ class FlightTest extends TestCase public function testKeepThePreviousStateOfOneViewComponentByDefault(): void { - $this->expectOutputString(<<<'html' + $html = <<<'html'