Skip to content

Commit

Permalink
Merge pull request #622 from flightphp/new-request-object
Browse files Browse the repository at this point in the history
Added ability to generate new requests/responses on duplicate start()
  • Loading branch information
n0nag0n authored Feb 21, 2025
2 parents f411592 + 7dd52c9 commit b6ab088
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 28 deletions.
17 changes: 16 additions & 1 deletion flight/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -476,6 +479,19 @@ public function _start(): void
{
$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();
Expand All @@ -498,7 +514,6 @@ public function _start(): void

// Route the request
$failedMiddlewareCheck = false;

while ($route = $router->route($request)) {
$params = array_values($route->params);

Expand Down
4 changes: 2 additions & 2 deletions flight/net/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ public function init(array $properties = []): self
$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 = [];
Expand Down
24 changes: 24 additions & 0 deletions tests/EngineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,30 @@ public function getInitializedVar()
$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 {
Expand Down
83 changes: 83 additions & 0 deletions tests/FlightAsyncTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace tests;

use Flight;
use flight\Engine;
use PHPUnit\Framework\TestCase;

class FlightAsyncTest extends TestCase
{
public static function setUpBeforeClass(): void
{
Flight::setEngine(new Engine());
}

protected function setUp(): void
{
$_SERVER = [];
$_REQUEST = [];
}

protected function tearDown(): void
{
unset($_REQUEST);
unset($_SERVER);
}

// Checks that default components are loaded
public function testSingleRoute()
{
Flight::route('GET /', function () {
echo 'hello world';
});

$this->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();
}
}
9 changes: 7 additions & 2 deletions tests/FlightTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -378,15 +378,20 @@ public function testDoesNotPreserveVarsWhenFlagIsDisabled(

public function testKeepThePreviousStateOfOneViewComponentByDefault(): void
{
$this->expectOutputString(<<<'html'
$html = <<<'html'
<div>Hi</div>
<div>Hi</div>
<input type="number" />
<input type="number" />

html);
html;

// if windows replace \n with \r\n
$html = str_replace("\n", PHP_EOL, $html);

$this->expectOutputString($html);

Flight::render('myComponent', ['prop' => 'Hi']);
Flight::render('myComponent');
Expand Down
18 changes: 9 additions & 9 deletions tests/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function testInitUrlSameAsBaseDirectory()
'base' => '/vagrant/public',
'query' => new Collection(),
'type' => '',
'method' => 'GET'
'method' => 'GET'
]);
$this->assertEquals('/flightphp', $request->url);
}
Expand All @@ -174,7 +174,7 @@ public function testInitNoUrl()
'url' => '',
'base' => '/vagrant/public',
'type' => '',
'method' => 'GET'
'method' => 'GET'
]);
$this->assertEquals('/', $request->url);
}
Expand All @@ -193,13 +193,13 @@ public function testInitWithJsonBody()
'data' => new Collection(),
'query' => new Collection(),
'stream_path' => $stream_path,
'method' => 'POST'
'method' => 'POST'
]);
$this->assertEquals([ 'foo' => 'bar' ], $request->data->getData());
$this->assertEquals('{"foo":"bar"}', $request->getBody());
}

public function testInitWithFormBody()
public function testInitWithFormBody()
{
// create dummy file to pull request body from
$tmpfile = tmpfile();
Expand All @@ -213,12 +213,12 @@ public function testInitWithFormBody()
'data' => new Collection(),
'query' => new Collection(),
'stream_path' => $stream_path,
'method' => 'PATCH'
'method' => 'PATCH'
]);
$this->assertEquals([
'foo' => 'bar',
'baz' => 'qux'
], $request->data->getData());
$this->assertEquals([
'foo' => 'bar',
'baz' => 'qux'
], $request->data->getData());
$this->assertEquals('foo=bar&baz=qux', $request->getBody());
}

Expand Down
43 changes: 29 additions & 14 deletions tests/ViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,20 @@ public function testDoesNotPreserveVarsWhenFlagIsDisabled(

public function testKeepThePreviousStateOfOneViewComponentByDefault(): void
{
$this->expectOutputString(<<<'html'
$html = <<<'html'
<div>Hi</div>
<div>Hi</div>
<input type="number" />
<input type="number" />

html);
html;

// if windows replace \n with \r\n
$html = str_replace("\n", PHP_EOL, $html);

$this->expectOutputString($html);

$this->view->render('myComponent', ['prop' => 'Hi']);
$this->view->render('myComponent');
Expand All @@ -197,36 +202,46 @@ public function testKeepThePreviousStateOfDataSettedBySetMethod(): void

$this->view->set('prop', 'bar');

$this->expectOutputString(<<<'html'
$html = <<<'html'
<div>qux</div>
<div>bar</div>

html);
html;

// if windows replace \n with \r\n
$html = str_replace("\n", PHP_EOL, $html);

$this->expectOutputString($html);

$this->view->render('myComponent', ['prop' => 'qux']);
$this->view->render('myComponent');
}

public static function renderDataProvider(): array
{
return [
[
<<<'html'
$html1 = <<<'html'
<div>Hi</div>
<div></div>

html,
['myComponent', ['prop' => 'Hi']],
'/^Undefined variable:? \$?prop$/'
],
[
<<<'html'
html;
$html2 = <<<'html'
<input type="number" />
<input type="text" />

html,
html;

$html1 = str_replace("\n", PHP_EOL, $html1);
$html2 = str_replace("\n", PHP_EOL, $html2);
return [
[
$html1,
['myComponent', ['prop' => 'Hi']],
'/^Undefined variable:? \$?prop$/'
],
[
$html2,
['input', ['type' => 'number']],
'/^.*$/'
],
Expand Down

0 comments on commit b6ab088

Please sign in to comment.