From bc055f44828b1ae87468bd80bf007e54ca5614ba Mon Sep 17 00:00:00 2001 From: Ronan Giron Date: Mon, 4 Nov 2024 14:20:09 +0100 Subject: [PATCH] Options for router Option: "X-Forwarded-Prefix" (boolean, or string) --- CHANGELOG.md | 7 ++++++ README.md | 6 +++++ src/Router.php | 22 ++++++++++++++++-- tests/RouterTest.php | 53 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 742e2ec..e2bac51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. This projec to [Semantic Versioning] (http://semver.org/). For change log format, use [Keep a Changelog] (http://keepachangelog.com/). +## [2.3.0] - 2024-11-04 + +### Added + +- Options for router +- Option: "X-Forwarded-Prefix" (boolean, or string) + ## [2.2.0] - 2024-10-18 ### Added diff --git a/README.md b/README.md index 46a9ac3..c13d6d4 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,12 @@ $router->addRoute( $route = $router->handle($serverRequest); ``` +#### Options + +| Options | Type | Description | +|--------------------|----------------|-------------------------------------------------------------------------------------------| +| X-Forwarded-Prefix | boolean/string | Default to **false**, **true** to use "X-Forwarded-Prefix" value or custom name of header | + #### Generate path You can generate a path with some parameters directly with `Router` object. diff --git a/src/Router.php b/src/Router.php index 7a39f40..f9fbe41 100644 --- a/src/Router.php +++ b/src/Router.php @@ -32,16 +32,23 @@ class Router implements RouterInterface use LoggerAwareTrait; use RouteSetTrait; + private array $options = [ + 'X-Forwarded-Prefix' => false, + ]; + /** * Router constructor. * + * @param array $options * @param LoggerInterface|null $logger */ - public function __construct(?LoggerInterface $logger = null) + public function __construct(array $options = [], ?LoggerInterface $logger = null) { if (null !== $logger) { $this->setLogger($logger); } + + $this->options = array_replace($this->options, $options); } /** @@ -97,7 +104,18 @@ public function generate(string $name, array|RouteAttributes $parameters = []): throw new NotFoundException(sprintf('Route "%s" does not exists', $name)); } - return $route->generate($parameters); + $str = $route->generate($parameters); + + // X-Forwarded-Prefix + if (false !== $this->options['X-Forwarded-Prefix']) { + $xForwardedPrefix = $this->options['X-Forwarded-Prefix'] === true ? 'X-Forwarded-Prefix' : (string)$this->options['X-Forwarded-Prefix']; + $xForwardedPrefix = 'HTTP_' . strtoupper(str_replace('-', '_', $xForwardedPrefix)); + if (!empty($prefix = $_SERVER[$xForwardedPrefix] ?? null)) { + $str = '/' . trim($prefix, '/') . $str; + } + } + + return $str; } private function generateParameters(array|RouteAttributes $parameters = []): array diff --git a/tests/RouterTest.php b/tests/RouterTest.php index ec96288..127bc23 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -22,6 +22,11 @@ class RouterTest extends AbstractTestCase { + protected function setUp(): void + { + $_SERVER['HTTP_X_FORWARDED_PREFIX'] = null; + } + public function testSerialization() { $router = new Router; @@ -101,6 +106,54 @@ public function testGenerate() ); } + public function testGenerate_withForwardedPrefix_enable() + { + $_SERVER['HTTP_X_FORWARDED_PREFIX'] = '/super-prefix/'; + + $router = new Router(['X-Forwarded-Prefix' => true]); + $router->addRoute(new Route('/path/{attr1}/sub-path', name: 'route1')); + + $this->assertEquals( + '/super-prefix/path/test/sub-path', + $router->generate( + 'route1', + ['attr1' => 'test'] + ) + ); + } + + public function testGenerate_withForwardedPrefix_disable() + { + $_SERVER['HTTP_X_FORWARDED_PREFIX'] = '/super-prefix/'; + + $router = new Router(['X-Forwarded-Prefix' => false]); + $router->addRoute(new Route('/path/{attr1}/sub-path', name: 'route1')); + + $this->assertEquals( + '/path/test/sub-path', + $router->generate( + 'route1', + ['attr1' => 'test'] + ) + ); + } + + public function testGenerate_withForwardedPrefix_custom() + { + $_SERVER['HTTP_X_FORWARDED_PREFIX_CUSTOM'] = '/super-prefix/'; + + $router = new Router(['X-Forwarded-Prefix' => 'X-Forwarded-Prefix-Custom']); + $router->addRoute(new Route('/path/{attr1}/sub-path', name: 'route1')); + + $this->assertEquals( + '/super-prefix/path/test/sub-path', + $router->generate( + 'route1', + ['attr1' => 'test'] + ) + ); + } + public function testGenerateWithMissingAttributes() { $router = new Router;