Skip to content

Commit

Permalink
Add debug stuff to application's fallback handler (#145)
Browse files Browse the repository at this point in the history
* Wrap application's fallback handler to provider debug headers

* Apply fixes from StyleCI

* Ignore class

* Fix tests

* Refactor

* Fix test

* Add workaround for Subfolder middleware

* Fix tests

* Fix tests

* Add middleware dispatcher

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
  • Loading branch information
xepozz and StyleCIBot committed Jun 21, 2024
1 parent cbb26ce commit 9e86aa5
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 5 deletions.
1 change: 1 addition & 0 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions config/di-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -34,4 +36,14 @@
)
);
},
HttpApplicationWrapper::class => [
'__construct()' => [
'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'],
],
],
RouteCollectorWrapper::class => [
'__construct()' => [
'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'],
],
],
];
4 changes: 4 additions & 0 deletions config/params.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,6 +27,9 @@
'enabled' => true,
'allowedIPs' => ['127.0.0.1', '::1'],
'allowedHosts' => [],
'middlewares' => [
DebugHeaders::class,
],
'inspector' => [
'commandMap' => [
'tests' => $testCommands,
Expand Down
37 changes: 37 additions & 0 deletions src/Debug/Http/HttpApplicationWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Http;

use Closure;
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
use Yiisoft\Yii\Debug\Api\Debug\Middleware\MiddlewareDispatcherMiddleware;
use Yiisoft\Yii\Http\Application;

final readonly class HttpApplicationWrapper
{
public function __construct(
private MiddlewareDispatcher $middlewareDispatcher,
private array $middlewareDefinitions,
) {
}

public function wrap(Application $application): void

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)
{
$middlewareDispatcher = $this->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);
}
}
20 changes: 20 additions & 0 deletions src/Debug/Http/RouteCollectorWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Http;

use Yiisoft\Router\RouteCollectorInterface;

final class RouteCollectorWrapper
{
public function __construct(
private array $middlewareDefinitions,
) {
}

public function wrap(RouteCollectorInterface $routeCollector): void
{
$routeCollector->prependMiddleware(...$this->middlewareDefinitions);
}
}
24 changes: 24 additions & 0 deletions src/Debug/Middleware/MiddlewareDispatcherMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;

final class MiddlewareDispatcherMiddleware implements MiddlewareInterface
{
public function __construct(
public MiddlewareDispatcher $middlewareDispatcher
) {
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
return $this->middlewareDispatcher->dispatch($request, $handler);
}
}
22 changes: 19 additions & 3 deletions src/Debug/Provider/DebugApiProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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) {

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)
$applicationWrapper = $container->get(HttpApplicationWrapper::class);
$applicationWrapper->wrap($application);

return $application;
},
];
}
}
14 changes: 12 additions & 2 deletions tests/Unit/Debug/Provider/DebugApiProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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));
}
}

0 comments on commit 9e86aa5

Please sign in to comment.