diff --git a/example/example.php b/example/example.php index df7a6ee..16de34c 100644 --- a/example/example.php +++ b/example/example.php @@ -5,6 +5,7 @@ require_once \dirname(__DIR__) . '/vendor/autoload.php'; use Gacela\Router\Entities\Request; +use Gacela\Router\Entities\Response; use Gacela\Router\Router; use Gacela\Router\Routes; @@ -34,6 +35,14 @@ public function customAction(int $number = 0): string { return "customAction(number: {$number})"; } + + public function customHeaders(): Response + { + return new Response('{"custom": "headers"}', [ + 'Access-Control-Allow-Origin: *', + 'Content-Type: application/json', + ]); + } } Router::configure(static function (Routes $routes): void { @@ -48,4 +57,7 @@ public function customAction(int $number = 0): string # Try it out: http://localhost:8081/custom $routes->any('custom', Controller::class); + + # Try it out: http://localhost:8081/headers + $routes->any('headers', Controller::class, 'customHeaders'); }); diff --git a/src/Router/Entities/JsonResponse.php b/src/Router/Entities/JsonResponse.php index eb3f6c6..a70a9da 100644 --- a/src/Router/Entities/JsonResponse.php +++ b/src/Router/Entities/JsonResponse.php @@ -4,17 +4,18 @@ namespace Gacela\Router\Entities; +use function in_array; + final class JsonResponse extends Response { - public function __construct(array $json) + /** + * @param list $headers + */ + public function __construct(array $json, array $headers = []) { - parent::__construct(json_encode($json, JSON_THROW_ON_ERROR)); - } - - public function __toString(): string - { - header('Content-Type: application/json'); - - return parent::__toString(); + if (!in_array('Content-Type: application/json', $headers, true)) { + $headers[] = 'Content-Type: application/json'; + } + parent::__construct(json_encode($json, JSON_THROW_ON_ERROR), $headers); } } diff --git a/src/Router/Entities/Response.php b/src/Router/Entities/Response.php index 21a6bac..2272fc3 100644 --- a/src/Router/Entities/Response.php +++ b/src/Router/Entities/Response.php @@ -6,13 +6,21 @@ class Response { + /** + * @param list $headers + */ public function __construct( - private string $body, + private string $content, + private array $headers = [], ) { } public function __toString(): string { - return $this->body; + foreach ($this->headers as $header) { + header($header); + } + + return $this->content; } } diff --git a/tests/Feature/Router/RouterResponseTest.php b/tests/Feature/Router/RouterResponseTest.php index 6a1e04b..8a2c0d5 100644 --- a/tests/Feature/Router/RouterResponseTest.php +++ b/tests/Feature/Router/RouterResponseTest.php @@ -48,4 +48,60 @@ public function test_json_response(): void ], ], $this->headers()); } + + public function test_response_headers(): void + { + $_SERVER['REQUEST_URI'] = 'https://example.org/uri'; + $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET; + + Router::configure(static function (Routes $routes): void { + $routes->get('uri', static fn () => new Response('{"key":"value"}', [ + 'Access-Control-Allow-Origin: *', + 'Content-Type: application/json', + ])); + }); + + $this->expectOutputString('{"key":"value"}'); + + self::assertSame([ + [ + 'header' => 'Access-Control-Allow-Origin: *', + 'replace' => true, + 'response_code' => 0, + ], + [ + 'header' => 'Content-Type: application/json', + 'replace' => true, + 'response_code' => 0, + ], + ], $this->headers()); + } + + public function test_json_response_headers(): void + { + $_SERVER['REQUEST_URI'] = 'https://example.org/uri'; + $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET; + + Router::configure(static function (Routes $routes): void { + $routes->get('uri', static fn () => new JsonResponse(['key' => 'value'], [ + 'Access-Control-Allow-Origin: *', + 'Content-Type: application/json', + ])); + }); + + $this->expectOutputString('{"key":"value"}'); + + self::assertSame([ + [ + 'header' => 'Access-Control-Allow-Origin: *', + 'replace' => true, + 'response_code' => 0, + ], + [ + 'header' => 'Content-Type: application/json', + 'replace' => true, + 'response_code' => 0, + ], + ], $this->headers()); + } }