From 33676872ed3baef9bae1dfe6943d9099ec5b1ff2 Mon Sep 17 00:00:00 2001 From: Austin Collier Date: Wed, 22 May 2024 23:17:51 -0600 Subject: [PATCH] Maintains headers on redirect, error, and halt. Added jsonHalt --- flight/Engine.php | 41 ++++++++++++++++++++++++++++++++++++----- flight/Flight.php | 2 ++ tests/EngineTest.php | 10 ++++++++++ tests/RouterTest.php | 4 ++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/flight/Engine.php b/flight/Engine.php index 2559810..a1378a6 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -57,6 +57,8 @@ use flight\net\Route; * @method void redirect(string $url, int $code = 303) Redirects the current request to another URL. * @method void json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) * Sends a JSON response. + * @method void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) + * Sends a JSON response and immediately halts the request. * @method void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) * Sends a JSONP response. * @@ -73,7 +75,7 @@ class Engine */ private const MAPPABLE_METHODS = [ 'start', 'stop', 'route', 'halt', 'error', 'notFound', - 'render', 'redirect', 'etag', 'lastModified', 'json', 'jsonp', + 'render', 'redirect', 'etag', 'lastModified', 'json', 'jsonHalt', 'jsonp', 'post', 'put', 'patch', 'delete', 'group', 'getUrl' ]; @@ -608,7 +610,7 @@ class Engine try { $this->response() - ->clear() + ->clearBody() ->status(500) ->write($msg) ->send(); @@ -735,7 +737,7 @@ class Engine public function _halt(int $code = 200, string $message = '', bool $actuallyExit = true): void { $this->response() - ->clear() + ->clearBody() ->status($code) ->write($message) ->send(); @@ -750,7 +752,7 @@ class Engine $output = '

404 Not Found

The page you have requested could not be found.

'; $this->response() - ->clear() + ->clearBody() ->status(404) ->write($output) ->send(); @@ -775,7 +777,7 @@ class Engine } $this->response() - ->clear() + ->clearBody() ->status($code) ->header('Location', $url) ->send(); @@ -829,6 +831,33 @@ class Engine } } + /** + * Sends a JSON response and halts execution immediately. + * + * @param mixed $data JSON data + * @param int $code HTTP status code + * @param bool $encode Whether to perform JSON encoding + * @param string $charset Charset + * @param int $option Bitmask Json constant such as JSON_HEX_QUOT + * + * @throws Exception + */ + public function _jsonHalt( + $data, + int $code = 200, + bool $encode = true, + string $charset = 'utf-8', + int $option = 0 + ): void { + $this->json($data, $code, $encode, $charset, $option); + $jsonBody = $this->response()->getBody(); + if ($this->response()->v2_output_buffering === false) { + $this->response()->clearBody(); + $this->response()->send(); + } + $this->halt($code, $jsonBody, empty(getenv('PHPUNIT_TEST'))); + } + /** * Sends a JSONP response. * @@ -877,6 +906,7 @@ class Engine isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $id ) { + $this->response()->clear(); $this->halt(304, '', empty(getenv('PHPUNIT_TEST'))); } } @@ -894,6 +924,7 @@ class Engine isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $time ) { + $this->response()->clear(); $this->halt(304, '', empty(getenv('PHPUNIT_TEST'))); } } diff --git a/flight/Flight.php b/flight/Flight.php index a04ad80..207d44b 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -68,6 +68,8 @@ require_once __DIR__ . '/autoload.php'; * @method static void redirect(string $url, int $code = 303) Redirects to another URL. * @method static void json(mixed $data, int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512) * Sends a JSON response. + * @method void jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) + * Sends a JSON response and immediately halts the request. * @method static void jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = "utf8", int $encodeOption = 0, int $encodeDepth = 512) * Sends a JSONP response. * @method static void error(Throwable $exception) Sends an HTTP 500 response. diff --git a/tests/EngineTest.php b/tests/EngineTest.php index 3c24c88..93f3ff7 100644 --- a/tests/EngineTest.php +++ b/tests/EngineTest.php @@ -370,6 +370,16 @@ class EngineTest extends TestCase $this->assertEquals(200, $engine->response()->status()); } + public function testJsonHalt() + { + $engine = new Engine(); + $this->expectOutputString('{"key1":"value1","key2":"value2"}'); + $engine->jsonHalt(['key1' => 'value1', 'key2' => 'value2']); + $this->assertEquals('application/json; charset=utf-8', $engine->response()->headers()['Content-Type']); + $this->assertEquals(200, $engine->response()->status()); + $this->assertEquals('{"key1":"value1","key2":"value2"}', $engine->response()->getBody()); + } + public function testJsonP() { $engine = new Engine(); diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 8906168..f0ac765 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -631,6 +631,10 @@ class RouterTest extends TestCase $this->router->rewind(); $result = $this->router->valid(); $this->assertTrue($result); + + $this->router->previous(); + $result = $this->router->valid(); + $this->assertFalse($result); } public function testGetRootUrlByAlias()