From: Tim Düsterhus Date: Thu, 19 May 2022 14:09:25 +0000 (+0200) Subject: Move the cache-control adjustments from RequestHandler into a middleware X-Git-Tag: 6.0.0_Alpha_1~1266^2~7 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=55bd7dd595298224f4675eda58452a82b4cb8613;p=GitHub%2FWoltLab%2FWCF.git Move the cache-control adjustments from RequestHandler into a middleware --- diff --git a/wcfsetup/install/files/lib/http/middleware/EnforceCacheControlPrivate.class.php b/wcfsetup/install/files/lib/http/middleware/EnforceCacheControlPrivate.class.php new file mode 100644 index 0000000000..217d1d0fb8 --- /dev/null +++ b/wcfsetup/install/files/lib/http/middleware/EnforceCacheControlPrivate.class.php @@ -0,0 +1,62 @@ + + * @package WoltLabSuite\Core\Http\Middleware + * @since 5.6 + */ +final class EnforceCacheControlPrivate implements MiddlewareInterface +{ + /** + * @inheritDoc + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $response = $handler->handle($request); + + if ($response instanceof LegacyPlaceholderResponse) { + return $response; + } + + // Storing responses in a shared cache is unsafe, because they all contain session specific information. + // Add the 'private' value to the cache-control header and remove any 'public' value. + $cacheControl = [ + 'private', + ]; + foreach (Header::normalize($response->getHeader('cache-control')) as $value) { + [$field] = \explode('=', $value, 2); + + // Prevent duplication of the 'private' field. + if ($field === 'private') { + continue; + } + + // Drop the 'public' field. + if ($field === 'public') { + continue; + } + + $cacheControl[] = $value; + } + + return $response->withHeader( + 'cache-control', + // Manually imploding the fields is not required as per strict reading of the HTTP standard, + // but having duplicate 'cache-control' headers in the response certainly looks odd. + \implode(', ', $cacheControl) + ); + } +} diff --git a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php index 1de1d9aa60..a479f39750 100644 --- a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php @@ -2,11 +2,11 @@ namespace wcf\system\request; -use GuzzleHttp\Psr7\Header; use Laminas\Diactoros\ServerRequestFactory; use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Psr\Http\Message\ResponseInterface; use wcf\http\LegacyPlaceholderResponse; +use wcf\http\middleware\EnforceCacheControlPrivate; use wcf\http\Pipeline; use wcf\system\application\ApplicationHandler; use wcf\system\box\BoxHandler; @@ -104,7 +104,9 @@ class RequestHandler extends SingletonFactory \header('cross-origin-resource-policy: same-site'); } - $pipeline = new Pipeline([]); + $pipeline = new Pipeline([ + new EnforceCacheControlPrivate(), + ]); $this->sendPsr7Response( $pipeline->process($psrRequest, $this->getActiveRequest()) @@ -125,34 +127,6 @@ class RequestHandler extends SingletonFactory return; } - // Storing responses in a shared cache is unsafe, because they all contain session specific information. - // Add the 'private' value to the cache-control header and remove any 'public' value. - $cacheControl = [ - 'private', - ]; - foreach (Header::normalize($response->getHeader('cache-control')) as $value) { - [$field] = \explode('=', $value, 2); - - // Prevent duplication of the 'private' field. - if ($field === 'private') { - continue; - } - - // Drop the 'public' field. - if ($field === 'public') { - continue; - } - - $cacheControl[] = $value; - } - - $response = $response->withHeader( - 'cache-control', - // Manually imploding the fields is not required as per strict reading of the HTTP standard, - // but having duplicate 'cache-control' headers in the response certainly looks odd. - \implode(', ', $cacheControl) - ); - $response->withHeader('x-frame-options', 'SAMEORIGIN'); $emitter = new SapiEmitter();