diff --git a/composer.json b/composer.json index 75383809..a5142160 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "require": { "php": ">=7.2.0", "cakephp/cakephp": "^4.0", - "markstory/mini-asset": ">=1.4.0 <2.0.0" + "markstory/mini-asset": ">=1.4.0 <2.0.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0" }, "require-dev": { "phpunit/phpunit": "~8.5.0", diff --git a/src/Middleware/AssetCompressMiddleware.php b/src/Middleware/AssetCompressMiddleware.php index be680c99..6bfa8008 100644 --- a/src/Middleware/AssetCompressMiddleware.php +++ b/src/Middleware/AssetCompressMiddleware.php @@ -7,13 +7,18 @@ use AssetCompress\Factory; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; +use Cake\Http\Response; use Exception; use MiniAsset\AssetConfig; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; /** * PSR7 Compatible middleware for the new HTTP stack. */ -class AssetCompressMiddleware +class AssetCompressMiddleware implements MiddlewareInterface { /** * Object containing configuration settings for asset compressor @@ -38,25 +43,24 @@ public function __construct(?AssetConfig $config = null) } /** - * Get an asset or delegate to the next middleware + * Callable implementation for the middleware stack. * * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @param \Psr\Http\Message\ResponseInterface $response The response. - * @param callable $next Callback to invoke the next middleware. - * @return \Psr\Http\Message\ResponseInterface A response + * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. + * @return \Psr\Http\Message\ResponseInterface A response. */ - public function __invoke($request, $response, $next) + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $config = $this->config; $production = !Configure::read('debug'); if ($production && !$config->general('alwaysEnableController')) { - return $next($request, $response); + return $handler->handle($request); } // Make sure the request looks like an asset. $targetName = $this->getName($config, $request->getUri()->getPath()); if (!$targetName) { - return $next($request, $response); + return $handler->handle($request); } $queryParams = $request->getQueryParams(); @@ -66,7 +70,7 @@ public function __invoke($request, $response, $next) $factory = new Factory($config); $assets = $factory->assetCollection(); if (!$assets->contains($targetName)) { - return $next($request, $response); + return $handler->handle($request); } $build = $assets->get($targetName); @@ -77,19 +81,20 @@ public function __invoke($request, $response, $next) throw new NotFoundException($e->getMessage()); } - return $this->respond($response, $contents, $build); + return $this->respond($contents, $build); } /** * Respond with the asset. * - * @param \Psr\Http\Message\ResponseInterface $response The response to augment * @param string $contents The asset contents. * @param \MiniAsset\AssetTarget $build The build target. * @return \Psr\Http\Message\ResponseInterface */ - protected function respond($response, $contents, $build) + protected function respond($contents, $build) { + $response = new Response(); + // Deliver built asset. $body = $response->getBody(); $body->write($contents); diff --git a/tests/TestCase/Middleware/AssetCompressMiddlewareTest.php b/tests/TestCase/Middleware/AssetCompressMiddlewareTest.php index 77a268bd..c2701acb 100644 --- a/tests/TestCase/Middleware/AssetCompressMiddlewareTest.php +++ b/tests/TestCase/Middleware/AssetCompressMiddlewareTest.php @@ -4,6 +4,7 @@ namespace AssetCompress\Test\TestCase\Middleware; use AssetCompress\Middleware\AssetCompressMiddleware; +use AssetCompress\Test\TestCase\Middleware\RequestHandlerStub; use Cake\Core\Configure; use Cake\TestSuite\TestCase; use Laminas\Diactoros\Response; @@ -35,9 +36,11 @@ public function setUp(): void $this->middleware = new AssetCompressMiddleware($config); $this->request = new ServerRequest(); $this->response = new Response(); - $this->next = function () { + $this->handler = new RequestHandlerStub(function () { $this->nextInvoked = true; - }; + + return new Response(); + }); } /** @@ -61,9 +64,7 @@ public function testBuildFile() $uri = $this->request->getUri()->withPath('/cache_js/libs.js'); $request = $this->request->withUri($uri); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); - + $result = $this->middleware->process($request, $this->handler); $this->assertEquals('application/javascript', $result->getHeaderLine('Content-Type')); $body = $result->getBody()->getContents(); @@ -83,8 +84,7 @@ public function testPluginIniBuildFile() $uri = $this->request->getUri()->withPath('/cache_js/TestAssetIni.libs.js'); $request = $this->request->withUri($uri); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); + $result = $this->middleware->process($request, $this->handler); $this->assertEquals('application/javascript', $result->getHeaderLine('Content-Type')); @@ -103,8 +103,7 @@ public function testBuildFileIsCached() $uri = $this->request->getUri()->withPath('/cache_js/libs.js'); $request = $this->request->withUri($uri); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); + $result = $this->middleware->process($request, $this->handler); $body = $result->getBody()->getContents(); $this->assertEquals('application/javascript', $result->getHeaderLine('Content-Type')); @@ -120,9 +119,7 @@ public function testProductionMode() $uri = $this->request->getUri()->withPath('/cache_js/libs.js'); $request = $this->request->withUri($uri); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); - $this->assertNull($result); + $this->middleware->process($request, $this->handler); $this->assertTrue($this->nextInvoked); } @@ -143,8 +140,7 @@ public function testBuildThemedAsset() $request = $this->request->withUri($uri) ->withQueryParams(['theme' => 'Blue']); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); + $result = $this->middleware->process($request, $this->handler); $body = $result->getBody()->getContents(); $this->assertEquals('text/css', $result->getHeaderLine('Content-Type')); @@ -156,9 +152,7 @@ public function testDelegateOnUndefinedAsset() $uri = $this->request->getUri()->withPath('/cache_js/derpy.js'); $request = $this->request->withUri($uri); - $mw = $this->middleware; - $result = $mw($request, $this->response, $this->next); - $this->assertNull($result); + $this->middleware->process($request, $this->handler); $this->assertTrue($this->nextInvoked); } } diff --git a/tests/TestCase/Middleware/RequestHandlerStub.php b/tests/TestCase/Middleware/RequestHandlerStub.php new file mode 100644 index 00000000..efa313e4 --- /dev/null +++ b/tests/TestCase/Middleware/RequestHandlerStub.php @@ -0,0 +1,37 @@ +callable = $callable ?: function ($request) { + return new Response(); + }; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + return ($this->callable)($request); + } +}