From 62399539a4bb3b5346323d6b73ad66a154744d4d Mon Sep 17 00:00:00 2001 From: Christian Kuhn Date: Thu, 15 Feb 2018 02:20:19 +0100 Subject: [PATCH] [FEATURE] Allow deactivation of PSR-15 middlewares Similar to other places that use dependency configurations via arrays, the middleware stack configuration now allows disabling single middlewares by setting disabled=true. Change-Id: I42c741062b5f6952577e164939593f0553b1ad31 Resolves: #83907 Related: #83906 Related: #83725 Releases: master Reviewed-on: https://review.typo3.org/55725 Reviewed-by: Mathias Schreiber Tested-by: Mathias Schreiber Tested-by: TYPO3com Reviewed-by: Anja Leichsenring Tested-by: Anja Leichsenring Reviewed-by: Benjamin Franzke Reviewed-by: Christian Kuhn Tested-by: Christian Kuhn --- .../Classes/Http/MiddlewareStackResolver.php | 4 + .../core/Classes/Http/NormalizedParams.php | 2 +- ...-83725-SupportForPSR-15HTTPMiddlewares.rst | 49 +++++++---- .../Configuration/RequestMiddlewares.php | 8 ++ .../Configuration/RequestMiddlewares.php | 8 ++ .../Configuration/RequestMiddlewares.php | 11 +++ .../Unit/Http/MiddlewareStackResolverTest.php | 88 +++++++++++++++++++ 7 files changed, 151 insertions(+), 19 deletions(-) create mode 100644 typo3/sysext/core/Tests/Unit/Http/Fixtures/Package1/Configuration/RequestMiddlewares.php create mode 100644 typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2/Configuration/RequestMiddlewares.php create mode 100644 typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2Disables1/Configuration/RequestMiddlewares.php create mode 100644 typo3/sysext/core/Tests/Unit/Http/MiddlewareStackResolverTest.php diff --git a/typo3/sysext/core/Classes/Http/MiddlewareStackResolver.php b/typo3/sysext/core/Classes/Http/MiddlewareStackResolver.php index 68856be60f68..4d4b03917b67 100644 --- a/typo3/sysext/core/Classes/Http/MiddlewareStackResolver.php +++ b/typo3/sysext/core/Classes/Http/MiddlewareStackResolver.php @@ -118,6 +118,10 @@ protected function sanitizeMiddlewares(array $allMiddlewares): array $sanitizedMiddlewares = []; foreach ($middlewaresOfStack as $name => $middleware) { + if (isset($middleware['disabled']) && $middleware['disabled'] === true) { + // Skip this middleware if disabled by configuration + continue; + } $sanitizedMiddlewares[$name] = $middleware['target']; } diff --git a/typo3/sysext/core/Classes/Http/NormalizedParams.php b/typo3/sysext/core/Classes/Http/NormalizedParams.php index 6731d67723a9..008da9f0c756 100644 --- a/typo3/sysext/core/Classes/Http/NormalizedParams.php +++ b/typo3/sysext/core/Classes/Http/NormalizedParams.php @@ -21,7 +21,7 @@ /** * This class provides normalized server parameters in HTTP request context. * It normalizes reverse proxy scenarios and various other web server specific differences - * of native the PSR-7 request object parameters (->getServerParams() / $GLOBALS['_SERVER']). + * of the native PSR-7 request object parameters (->getServerParams() / $GLOBALS['_SERVER']). * * An instance of this class is available as PSR-7 ServerRequestInterface attribute: * $normalizedParams = $request->getAttribute('normalizedParams') diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-83725-SupportForPSR-15HTTPMiddlewares.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-83725-SupportForPSR-15HTTPMiddlewares.rst index 207178d0ec0d..80f1ce7c6ce8 100644 --- a/typo3/sysext/core/Documentation/Changelog/master/Feature-83725-SupportForPSR-15HTTPMiddlewares.rst +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-83725-SupportForPSR-15HTTPMiddlewares.rst @@ -37,21 +37,34 @@ To add a middleware to the "frontend" or "backend" middleware stack, create the .. code-block:: php - return [ - // stack name: currently 'frontend' or 'backend' - 'frontend' => [ - 'middleware-identifier' => [ - 'target' => \ACME\Ext\Middleware::class, - 'description' => '', - 'before' => [ - 'another-middleware-identifier', - ], - 'after' => [ - 'yet-another-middleware-identifier', - ], - ] - ] - ]; - - -.. index:: Backend, Frontend, PHP-API, NotScanned + return [ + // stack name: currently 'frontend' or 'backend' + 'frontend' => [ + 'middleware-identifier' => [ + 'target' => \ACME\Ext\Middleware::class, + 'description' => '', + 'before' => [ + 'another-middleware-identifier', + ], + 'after' => [ + 'yet-another-middleware-identifier', + ], + ] + ] + ]; + +If extensions need to shut down or substitute existing middlewares with an own solution, they can +disable an existing middleware by adding the following code in :file:`Configuration/RequestMiddlewares.php`: of their +extension. + +.. code-block:: php + + return [ + 'frontend' => [ + 'middleware-identifier' => [ + 'disabled' => true, + ], + ], + ]; + +.. index:: Backend, Frontend, PHP-API diff --git a/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package1/Configuration/RequestMiddlewares.php b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package1/Configuration/RequestMiddlewares.php new file mode 100644 index 000000000000..e43302148bbf --- /dev/null +++ b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package1/Configuration/RequestMiddlewares.php @@ -0,0 +1,8 @@ + [ + 'firstMiddleware' => [ + 'target' => 'aClassName', + ], + ] +]; diff --git a/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2/Configuration/RequestMiddlewares.php b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2/Configuration/RequestMiddlewares.php new file mode 100644 index 000000000000..6ebc2c9c3daf --- /dev/null +++ b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2/Configuration/RequestMiddlewares.php @@ -0,0 +1,8 @@ + [ + 'secondMiddleware' => [ + 'target' => 'anotherClassName', + ], + ] +]; diff --git a/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2Disables1/Configuration/RequestMiddlewares.php b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2Disables1/Configuration/RequestMiddlewares.php new file mode 100644 index 000000000000..a284dd5aac69 --- /dev/null +++ b/typo3/sysext/core/Tests/Unit/Http/Fixtures/Package2Disables1/Configuration/RequestMiddlewares.php @@ -0,0 +1,11 @@ + [ + 'firstMiddleware' => [ + 'disabled' => true, + ], + 'secondMiddleware' => [ + 'target' => 'anotherClassName', + ], + ] +]; diff --git a/typo3/sysext/core/Tests/Unit/Http/MiddlewareStackResolverTest.php b/typo3/sysext/core/Tests/Unit/Http/MiddlewareStackResolverTest.php new file mode 100644 index 000000000000..50747117c014 --- /dev/null +++ b/typo3/sysext/core/Tests/Unit/Http/MiddlewareStackResolverTest.php @@ -0,0 +1,88 @@ +prophesize(Package::class); + $package1->getPackagePath()->willReturn(__DIR__ . '/' . 'Fixtures/Package1/'); + $package2 = $this->prophesize(Package::class); + $package2->getPackagePath()->willReturn(__DIR__ . '/' . 'Fixtures/Package2/'); + $packageManagerProphecy = $this->prophesize(PackageManager::class); + $packageManagerProphecy->getActivePackages()->willReturn([$package1->reveal(), $package2->reveal()]); + $dependencyOrderingServiceProphecy = $this->prophesize(DependencyOrderingService::class); + $dependencyOrderingServiceProphecy->orderByDependencies(Argument::cetera())->willReturnArgument(0); + $phpFrontendCacheProphecy = $this->prophesize(PhpFrontend::class); + $phpFrontendCacheProphecy->has(Argument::cetera())->willReturn(false); + $phpFrontendCacheProphecy->set(Argument::cetera())->willReturn(false); + + $subject = new MiddlewareStackResolver( + $packageManagerProphecy->reveal(), + $dependencyOrderingServiceProphecy->reveal(), + $phpFrontendCacheProphecy->reveal() + ); + $expected = [ + 'secondMiddleware' => 'anotherClassName', + 'firstMiddleware' => 'aClassName', + ]; + $this->assertEquals($expected, $subject->resolve('testStack')); + } + + /** + * @test + */ + public function resolveAllowsDisablingAMiddleware() + { + $package1 = $this->prophesize(Package::class); + $package1->getPackagePath()->willReturn(__DIR__ . '/' . 'Fixtures/Package1/'); + $package2 = $this->prophesize(Package::class); + $package2->getPackagePath()->willReturn(__DIR__ . '/' . 'Fixtures/Package2Disables1/'); + $packageManagerProphecy = $this->prophesize(PackageManager::class); + $packageManagerProphecy->getActivePackages()->willReturn([$package1->reveal(), $package2->reveal()]); + $dependencyOrderingServiceProphecy = $this->prophesize(DependencyOrderingService::class); + $dependencyOrderingServiceProphecy->orderByDependencies(Argument::cetera())->willReturnArgument(0); + $phpFrontendCacheProphecy = $this->prophesize(PhpFrontend::class); + $phpFrontendCacheProphecy->has(Argument::cetera())->willReturn(false); + $phpFrontendCacheProphecy->set(Argument::cetera())->willReturn(false); + + $subject = new MiddlewareStackResolver( + $packageManagerProphecy->reveal(), + $dependencyOrderingServiceProphecy->reveal(), + $phpFrontendCacheProphecy->reveal() + ); + $expected = [ + // firstMiddleware is missing, RequestMiddlewares.php of Package2 sets disables=true on firstMiddleware + 'secondMiddleware' => 'anotherClassName', + ]; + $this->assertEquals($expected, $subject->resolve('testStack')); + } +}