diff --git a/composer-require-checker.json b/composer-require-checker.json index 23b3346..0528b49 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -4,6 +4,7 @@ "Yiisoft\\Assets\\AssetManager", "Yiisoft\\Assets\\AssetPublisherInterface", "Yiisoft\\Yii\\View\\ViewRenderer", + "Yiisoft\\Yii\\Http\\Application", "Codeception\\Event\\FailEvent", "Codeception\\Event\\PrintResultEvent", "Codeception\\Event\\TestEvent", diff --git a/composer.json b/composer.json index f3c9455..9823507 100644 --- a/composer.json +++ b/composer.json @@ -51,6 +51,7 @@ "yiisoft/di": "^1.0", "yiisoft/friendly-exception": "^1.1", "yiisoft/http": "^1.2", + "yiisoft/middleware-dispatcher": "^5.2", "yiisoft/router": "^3.0", "yiisoft/translator": "^3.0", "yiisoft/var-dumper": "^1.4", diff --git a/config/di-web.php b/config/di-web.php index 4836e98..1e17aec 100644 --- a/config/di-web.php +++ b/config/di-web.php @@ -5,6 +5,8 @@ use Cycle\Database\DatabaseProviderInterface; use Psr\Container\ContainerInterface; use Yiisoft\Db\Connection\ConnectionInterface; +use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepository; use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepositoryInterface; use Yiisoft\Yii\Debug\Api\Inspector\Database\Cycle\CycleSchemaProvider; @@ -34,4 +36,14 @@ ) ); }, + HttpApplicationWrapper::class => [ + '__construct()' => [ + 'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'], + ], + ], + RouteCollectorWrapper::class => [ + '__construct()' => [ + 'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'], + ], + ], ]; diff --git a/config/params.php b/config/params.php index b6c42ba..9630fc8 100644 --- a/config/params.php +++ b/config/params.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Codeception\Extension; +use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; use Yiisoft\Yii\Debug\Api\Inspector\Command\CodeceptionCommand; use Yiisoft\Yii\Debug\Api\Inspector\Command\PHPUnitCommand; use Yiisoft\Yii\Debug\Api\Inspector\Command\PsalmCommand; @@ -26,6 +27,9 @@ 'enabled' => true, 'allowedIPs' => ['127.0.0.1', '::1'], 'allowedHosts' => [], + 'middlewares' => [ + DebugHeaders::class, + ], 'inspector' => [ 'commandMap' => [ 'tests' => $testCommands, diff --git a/src/Debug/Http/HttpApplicationWrapper.php b/src/Debug/Http/HttpApplicationWrapper.php new file mode 100644 index 0000000..c3b9b5a --- /dev/null +++ b/src/Debug/Http/HttpApplicationWrapper.php @@ -0,0 +1,37 @@ +middlewareDispatcher; + $middlewareDefinitions = $this->middlewareDefinitions; + + $closure = Closure::bind(static function (Application $application) use ( + $middlewareDispatcher, + $middlewareDefinitions, + ) { + $application->dispatcher = $middlewareDispatcher->withMiddlewares([ + ...$middlewareDefinitions, + ['class' => MiddlewareDispatcherMiddleware::class, '$middlewareDispatcher' => $application->dispatcher], + ]);; + }, null, $application); + + $closure($application); + } +} diff --git a/src/Debug/Http/RouteCollectorWrapper.php b/src/Debug/Http/RouteCollectorWrapper.php new file mode 100644 index 0000000..c31fe75 --- /dev/null +++ b/src/Debug/Http/RouteCollectorWrapper.php @@ -0,0 +1,20 @@ +prependMiddleware(...$this->middlewareDefinitions); + } +} diff --git a/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php b/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php new file mode 100644 index 0000000..4cdaf74 --- /dev/null +++ b/src/Debug/Middleware/MiddlewareDispatcherMiddleware.php @@ -0,0 +1,24 @@ +middlewareDispatcher->dispatch($request, $handler); + } +} diff --git a/src/Debug/Provider/DebugApiProvider.php b/src/Debug/Provider/DebugApiProvider.php index d62d5be..7de2b6a 100644 --- a/src/Debug/Provider/DebugApiProvider.php +++ b/src/Debug/Provider/DebugApiProvider.php @@ -7,7 +7,9 @@ use Psr\Container\ContainerInterface; use Yiisoft\Di\ServiceProviderInterface; use Yiisoft\Router\RouteCollectorInterface; -use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; +use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; +use Yiisoft\Yii\Http\Application; final class DebugApiProvider implements ServiceProviderInterface { @@ -22,10 +24,24 @@ public function getDefinitions(): array public function getExtensions(): array { return [ - RouteCollectorInterface::class => static function (ContainerInterface $container, RouteCollectorInterface $routeCollector) { - $routeCollector->prependMiddleware(DebugHeaders::class); + RouteCollectorInterface::class => static function ( + ContainerInterface $container, + RouteCollectorInterface $routeCollector + ) { + /** + * Register debug middlewares twice because a `Subfolder` middleware may rewrite base URL + */ + $routerCollectionWrapper = $container->get(RouteCollectorWrapper::class); + $routerCollectionWrapper->wrap($routeCollector); + return $routeCollector; }, + Application::class => static function (ContainerInterface $container, Application $application) { + $applicationWrapper = $container->get(HttpApplicationWrapper::class); + $applicationWrapper->wrap($application); + + return $application; + }, ]; } } diff --git a/tests/Unit/Debug/Provider/DebugApiProviderTest.php b/tests/Unit/Debug/Provider/DebugApiProviderTest.php index 0ca8861..1d26116 100644 --- a/tests/Unit/Debug/Provider/DebugApiProviderTest.php +++ b/tests/Unit/Debug/Provider/DebugApiProviderTest.php @@ -5,7 +5,9 @@ namespace Yiisoft\Yii\Debug\Api\Tests\Unit\Debug\Provider; use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; use Yiisoft\Router\RouteCollectorInterface; +use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper; use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders; use Yiisoft\Yii\Debug\Api\Debug\Provider\DebugApiProvider; @@ -25,12 +27,20 @@ public function testExtension(): void $routeCollectorDecorator = $extensions[RouteCollectorInterface::class]; $this->assertIsCallable($routeCollectorDecorator); + $middlewares = [DebugHeaders::class]; + + $container = $this->createMock(ContainerInterface::class); + $container->expects($this->once()) + ->method('get') + ->with(RouteCollectorWrapper::class) + ->willReturn(new RouteCollectorWrapper($middlewares)); + $routeCollector = $this->createMock(RouteCollectorInterface::class); $routeCollector->expects($this->once()) ->method('prependMiddleware') - ->with(DebugHeaders::class) + ->with(...$middlewares) ->willReturn($routeCollector); - $this->assertSame($routeCollector, $routeCollectorDecorator($routeCollector)); + $this->assertSame($routeCollector, $routeCollectorDecorator($container, $routeCollector)); } }