Skip to content

Commit 6e6ca76

Browse files
authored
Merge pull request #52 from nlx-lars/feature/http-cache-2
FEATURE: Update to fos/http-cache:~2.0
2 parents 421c72f + 390e051 commit 6e6ca76

File tree

5 files changed

+92
-39
lines changed

5 files changed

+92
-39
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ before_script:
1616
"bin-dir": "bin"
1717
},
1818
"require": {
19-
"neos/neos": "^4.0",
19+
"neos/neos": "^5.0",
2020
"moc/varnish": "${VERSION}"
2121
},
2222
"require-dev": {

Classes/Http/CacheControlHeaderComponent.php

+15-19
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@
77
use MOC\Varnish\Cache\MetadataAwareStringFrontend;
88
use MOC\Varnish\Service\TokenStorage;
99
use Neos\ContentRepository\Domain\Model\NodeInterface;
10-
use Neos\ContentRepository\Exception\NodeException;
10+
use Neos\Flow\Annotations as Flow;
1111
use Neos\Flow\Http\Component\ComponentContext;
1212
use Neos\Flow\Http\Component\ComponentInterface;
1313
use Neos\Flow\Log\Utility\LogEnvironment;
1414
use Neos\Flow\Mvc\DispatchComponent;
1515
use Neos\Flow\Mvc\Exception\NoSuchArgumentException;
1616
use Neos\Flow\Property\PropertyMapper;
17-
use Neos\Flow\Annotations as Flow;
1817
use Psr\Log\LoggerInterface;
1918

2019
class CacheControlHeaderComponent implements ComponentInterface
2120
{
21+
2222
/**
23-
* @var ContentCacheAspect
24-
* @Flow\Inject
23+
* @var array
24+
* @Flow\InjectConfiguration(path="cacheHeaders")
2525
*/
26-
protected $contentCacheAspect;
26+
protected $cacheHeaderSettings;
2727

2828
/**
29-
* @var MetadataAwareStringFrontend
29+
* @var ContentCacheAspect
3030
* @Flow\Inject
3131
*/
32-
protected $contentCacheFrontend;
32+
protected $contentCacheAspect;
3333

3434
/**
3535
* @var TokenStorage
@@ -38,42 +38,38 @@ class CacheControlHeaderComponent implements ComponentInterface
3838
protected $tokenStorage;
3939

4040
/**
41-
* @Flow\Inject
4241
* @var LoggerInterface
42+
* @Flow\Inject
4343
*/
4444
protected $logger;
4545

4646
/**
47-
* @Flow\InjectConfiguration()
48-
* @var array
47+
* @var PropertyMapper
48+
* @Flow\Inject
4949
*/
50-
protected $cacheHeaderSettings;
50+
protected $propertyMapper;
5151

5252
/**
53-
* @Flow\Inject
54-
* @var PropertyMapper
53+
* @var MetadataAwareStringFrontend
5554
*/
56-
protected $propertyMapper;
55+
protected $contentCacheFrontend;
5756

5857
/**
5958
* @param ComponentContext $componentContext
6059
* @return void
61-
* @throws NodeException
6260
* @throws NoSuchArgumentException
6361
* @throws \Exception
6462
* @api
6563
*/
6664
public function handle(ComponentContext $componentContext)
6765
{
68-
6966
if ($this->cacheHeaderSettings['disabled'] ?? false) {
7067
$this->logger->debug(sprintf('Varnish cache headers disabled (see configuration setting MOC.Varnish.cacheHeaders.disabled)'), LogEnvironment::fromMethodName(__METHOD__));
7168
return;
7269
}
7370

7471
/** @var \Neos\Flow\Mvc\ActionRequest $actionRequest */
7572
$actionRequest = $componentContext->getParameter(DispatchComponent::class, 'actionRequest');
76-
7773
if (!$actionRequest->hasArgument('node') || !$actionRequest->getArgument('node')) {
7874
return;
7975
}
@@ -113,15 +109,15 @@ public function handle(ComponentContext $componentContext)
113109
list($tags, $cacheLifetime) = $this->getCacheTagsAndLifetime();
114110

115111
if (count($tags) > 0) {
116-
$modifiedResponse = $modifiedResponse->withHeader('X-Cache-Tags', $tags);
112+
$modifiedResponse = $modifiedResponse->withHeader('X-Cache-Tags', implode(',', $tags));
117113
}
118114

119115
$modifiedResponse = $modifiedResponse->withHeader('X-Site', $this->tokenStorage->getToken());
120116

121117
$nodeLifetime = $node->getProperty('cacheTimeToLive');
122118

123119
if ($nodeLifetime === '' || $nodeLifetime === null) {
124-
$defaultLifetime = $this->cacheHeaderSettings['cacheHeaders']['defaultSharedMaximumAge'] ?? null;
120+
$defaultLifetime = $this->cacheHeaderSettings['defaultSharedMaximumAge'] ?? null;
125121
$timeToLive = $defaultLifetime;
126122
if ($defaultLifetime === null) {
127123
$timeToLive = $cacheLifetime;
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace MOC\Varnish\Service\ProxyClient;
5+
6+
use FOS\HttpCache\ProxyClient\Varnish as FOSVarnish;
7+
8+
/**
9+
* Varnish ProxyClient that allows banning by tags and hosts
10+
* at the same time
11+
*/
12+
class Varnish extends FOSVarnish
13+
{
14+
15+
/**
16+
* @var array
17+
*/
18+
private $hosts = [];
19+
20+
public function forHosts(string ... $hosts): self
21+
{
22+
$this->hosts = $hosts;
23+
24+
return $this;
25+
}
26+
27+
public function ban(array $headers)
28+
{
29+
$headers = array_merge(
30+
$this->getHostHeader(),
31+
$headers
32+
);
33+
34+
return parent::ban($headers);
35+
}
36+
37+
private function getHostHeader(): array
38+
{
39+
switch (count($this->hosts)) {
40+
case 0:
41+
return [];
42+
case 1:
43+
return [self::HTTP_HEADER_HOST => current($this->hosts)];
44+
default:
45+
return [self::HTTP_HEADER_HOST => '^(' . implode('|', $this->hosts) . ')$'];
46+
}
47+
}
48+
49+
}

Classes/Service/VarnishBanService.php

+25-18
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
use FOS\HttpCache\Exception\ExceptionCollection;
88
use FOS\HttpCache\Exception\ProxyResponseException;
99
use FOS\HttpCache\Exception\ProxyUnreachableException;
10-
use FOS\HttpCache\Handler\TagHandler;
1110
use FOS\HttpCache\ProxyClient;
11+
use MOC\Varnish\Service\ProxyClient\Varnish;
1212
use Neos\Flow\Annotations as Flow;
1313

1414
/**
@@ -35,7 +35,7 @@ class VarnishBanService
3535
protected $settings;
3636

3737
/**
38-
* @var ProxyClient\Varnish
38+
* @var Varnish
3939
*/
4040
protected $varnishProxyClient;
4141

@@ -45,10 +45,9 @@ class VarnishBanService
4545
protected $cacheInvalidator;
4646

4747
/**
48-
* @var TagHandler
48+
* @param array $settings
49+
* @return void
4950
*/
50-
protected $tagHandler;
51-
5251
public function injectSettings(array $settings): void
5352
{
5453
$this->settings = $settings;
@@ -61,10 +60,15 @@ public function initializeObject(): void
6160
array_walk($varnishUrls, function (&$varnishUrl) {
6261
$varnishUrl = rtrim($varnishUrl, '/');
6362
});
64-
$this->varnishProxyClient = new ProxyClient\Varnish($varnishUrls);
65-
$this->varnishProxyClient->setDefaultBanHeader('X-Site', $this->tokenStorage->getToken());
63+
$httpDispatcher = new ProxyClient\HttpDispatcher($varnishUrls);
64+
$options = [
65+
'header_length' => $this->settings['maximumHeaderLength'] ?? 7500,
66+
'default_ban_headers' => [
67+
'X-Site' => $this->tokenStorage->getToken()
68+
]
69+
];
70+
$this->varnishProxyClient = new Varnish($httpDispatcher, $options);
6671
$this->cacheInvalidator = new CacheInvalidator($this->varnishProxyClient);
67-
$this->tagHandler = new TagHandler($this->cacheInvalidator, 'X-Cache-Tags', $this->settings['maximumHeaderLength'] ?? 7500);
6872
}
6973

7074
/**
@@ -81,6 +85,7 @@ public function initializeObject(): void
8185
*/
8286
public function banAll($domains = null, $contentType = null): void
8387
{
88+
$this->varnishProxyClient->forHosts(...$this->domainsToArray($domains));
8489
$this->cacheInvalidator->invalidateRegex('.*', $contentType, $domains);
8590
$this->logger->debug(sprintf('Clearing all Varnish cache%s%s', $domains ? ' for domains "' . (is_array($domains) ? implode(', ', $domains) : $domains) . '"' : '', $contentType ? ' with content type "' . $contentType . '"' : ''));
8691
$this->execute();
@@ -112,16 +117,9 @@ public function banByTags(array $tags, $domains = null): void
112117
$tags[$key] = strtr($tag, '.:', '_-');
113118
}
114119

115-
// Set specific domain before invalidating tags
116-
if ($domains) {
117-
$this->varnishProxyClient->setDefaultBanHeader(ProxyClient\Varnish::HTTP_HEADER_HOST, is_array($domains) ? '^(' . implode('|', $domains) . ')$' : $domains);
118-
}
119-
$this->tagHandler->invalidateTags($tags);
120-
// Unset specific domain after invalidating tags
121-
if ($domains) {
122-
$this->varnishProxyClient->setDefaultBanHeader(ProxyClient\Varnish::HTTP_HEADER_HOST, ProxyClient\Varnish::REGEX_MATCH_ALL);
123-
}
124-
$this->logger->debug(sprintf('Clearing Varnish cache for tags "%s"%s', implode(',', $tags), $domains ? ' for domains "' . (is_array($domains) ? implode(', ', $domains) : $domains) . '"' : ''));
120+
$this->varnishProxyClient->forHosts(...$this->domainsToArray($domains));
121+
$this->cacheInvalidator->invalidateTags($tags);
122+
$this->logger->debug(sprintf('Cleared Varnish cache for tags "%s"%s', implode(',', $tags), $domains ? ' for domains "' . (is_array($domains) ? implode(', ', $domains) : $domains) . '"' : ''));
125123
$this->execute();
126124
}
127125

@@ -141,4 +139,13 @@ protected function execute(): void
141139
}
142140
}
143141
}
142+
143+
/**
144+
* @param string|string[]|null $domains
145+
* @return array
146+
*/
147+
private function domainsToArray($domains = null): array
148+
{
149+
return is_array($domains) ? $domains : (is_string($domains) ? [$domains] : []);
150+
}
144151
}

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
],
3434
"require": {
3535
"neos/neos": "^5.0",
36-
"friendsofsymfony/http-cache": "~1.3"
36+
"friendsofsymfony/http-cache": "~2.0",
37+
"php-http/curl-client": "~1"
3738
},
3839
"autoload": {
3940
"psr-4": {

0 commit comments

Comments
 (0)