Skip to content

Commit 8a44856

Browse files
committed
add suport for prefix invalidation
1 parent 7805dc0 commit 8a44856

5 files changed

Lines changed: 104 additions & 11 deletions

File tree

doc/proxy-clients.rst

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ Supported invalidation methods
1919
Not all clients support all :ref:`invalidation methods <invalidation methods>`.
2020
This table provides of methods supported by each proxy client:
2121

22-
============= ======= ======= ======= ======= =======
23-
Client Purge Refresh Ban Tagging Clear
24-
============= ======= ======= ======= ======= =======
22+
============= ======= ======= ======= ======= ====== =======
23+
Client Purge Refresh Ban Tagging Prefix Clear
24+
============= ======= ======= ======= ======= ====== =======
2525
Varnish ✓ ✓ ✓ ✓
26-
Fastly ✓ ✓ ✓ ✓
26+
Fastly ✓ ✓ ✓
2727
NGINX ✓ ✓
28-
Symfony Cache ✓ ✓ ✓ (1) ✓ (1)
29-
Cloudflare ✓ ✓ (2) ✓
30-
Noop ✓ ✓ ✓ ✓ ✓
31-
Multiplexer ✓ ✓ ✓ ✓ ✓
32-
============= ======= ======= ======= ======= =======
28+
Symfony Cache ✓ ✓ ✓ (1) ✓ (1)
29+
Cloudflare ✓ ✓ (2) ✓ (2) ✓
30+
Noop ✓ ✓ ✓ ✓
31+
Multiplexer ✓ ✓ ✓ ✓
32+
============= ======= ======= ======= ======= ====== =======
3333

3434
| (1): Only when using `Toflar Psr6Store`_.
3535
| (2): Only available with `Cloudflare Enterprise`_.
@@ -357,7 +357,7 @@ the HttpDispatcher is not available for Cloudflare)::
357357
Cloudflare supports different cache purge methods depending on your account.
358358
All Cloudflare accounts support purging the cache by URL and clearing all
359359
cache items. You need a `Cloudflare Enterprise`_ account to purge by cache
360-
tags.
360+
tags or prefixes.
361361

362362
Zone identifier
363363
^^^^^^^^^^^^^^^

src/CacheInvalidator.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use FOS\HttpCache\Exception\UnsupportedProxyOperationException;
1919
use FOS\HttpCache\ProxyClient\Invalidation\BanCapable;
2020
use FOS\HttpCache\ProxyClient\Invalidation\ClearCapable;
21+
use FOS\HttpCache\ProxyClient\Invalidation\PrefixCapable;
2122
use FOS\HttpCache\ProxyClient\Invalidation\PurgeCapable;
2223
use FOS\HttpCache\ProxyClient\Invalidation\RefreshCapable;
2324
use FOS\HttpCache\ProxyClient\Invalidation\TagCapable;
@@ -216,6 +217,20 @@ public function invalidateTags(array $tags): static
216217
return $this;
217218
}
218219

220+
public function invalidatePrefixes(array $prefixes): static
221+
{
222+
if (!$this->cache instanceof PrefixCapable) {
223+
throw UnsupportedProxyOperationException::cacheDoesNotImplement('Prefixes');
224+
}
225+
if (!$prefixes) {
226+
return $this;
227+
}
228+
229+
$this->cache->invalidatePrefixes($prefixes);
230+
231+
return $this;
232+
}
233+
219234
/**
220235
* Invalidate URLs based on a regular expression for the URI, an optional
221236
* content type and optional limit to certain hosts.

src/ProxyClient/Cloudflare.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace FOS\HttpCache\ProxyClient;
1313

1414
use FOS\HttpCache\ProxyClient\Invalidation\ClearCapable;
15+
use FOS\HttpCache\ProxyClient\Invalidation\PrefixCapable;
1516
use FOS\HttpCache\ProxyClient\Invalidation\PurgeCapable;
1617
use FOS\HttpCache\ProxyClient\Invalidation\TagCapable;
1718
use Psr\Http\Message\RequestFactoryInterface;
@@ -27,7 +28,7 @@
2728
*
2829
* @author Simon Jones <simon@studio24.net>
2930
*/
30-
class Cloudflare extends HttpProxyClient implements ClearCapable, PurgeCapable, TagCapable
31+
class Cloudflare extends HttpProxyClient implements ClearCapable, PrefixCapable, PurgeCapable, TagCapable
3132
{
3233
/**
3334
* @see https://api.cloudflare.com/#getting-started-endpoints
@@ -87,6 +88,30 @@ public function invalidateTags(array $tags): static
8788
return $this;
8889
}
8990

91+
/**
92+
* {@inheritdoc}
93+
*
94+
* URL prefix only available with Cloudflare enterprise plans
95+
*
96+
* @see https://developers.cloudflare.com/api/resources/cache/methods/purge/
97+
*/
98+
public function invalidatePrefixes(array $prefixes): static
99+
{
100+
if (!$prefixes) {
101+
return $this;
102+
}
103+
104+
$this->queueRequest(
105+
'POST',
106+
sprintf(self::API_ENDPOINT.'/zones/%s/purge_cache', $this->options['zone_identifier']),
107+
[],
108+
false,
109+
json_encode(['prefixes' => $prefixes], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)
110+
);
111+
112+
return $this;
113+
}
114+
90115
/**
91116
* @see https://api.cloudflare.com/#zone-purge-files-by-url
92117
* @see https://developers.cloudflare.com/cache/how-to/purge-cache#purge-by-single-file-by-url For details on headers you can pass to clear the cache correctly
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSHttpCache package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace FOS\HttpCache\ProxyClient\Invalidation;
13+
14+
use FOS\HttpCache\ProxyClient\ProxyClient;
15+
16+
/**
17+
* An HTTP cache that supports invalidation by a cache tag, that is, removing
18+
* or expiring objects from the cache tagged with a given tag or set of tags.
19+
*
20+
* HTTP responses must carry the tags header name with the tags header value
21+
* for tag invalidation to work.
22+
*/
23+
interface PrefixCapable extends ProxyClient
24+
{
25+
/**
26+
* Remove/Expire cache objects based on cache tags.
27+
*
28+
* @param string[] $tags Tags that should be removed/expired from the cache. An empty tag list should be ignored.
29+
*/
30+
public function invalidatePrefixes(array $prefixes): static;
31+
}

tests/Unit/ProxyClient/CloudflareTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,28 @@ function (RequestInterface $request) {
7171
$cloudflare->invalidateTags(['tag-one', 'tag-two']);
7272
}
7373

74+
public function testInvalidatePrefixesPurge(): void
75+
{
76+
$cloudflare = $this->getProxyClient();
77+
78+
$this->httpDispatcher->shouldReceive('invalidate')->once()->with(
79+
\Mockery::on(
80+
function (RequestInterface $request) {
81+
$this->assertEquals('POST', $request->getMethod());
82+
$this->assertEquals('Bearer '.self::AUTH_TOKEN, current($request->getHeader('Authorization')));
83+
$this->assertEquals(sprintf('/client/v4/zones/%s/purge_cache', self::ZONE_IDENTIFIER), $request->getRequestTarget());
84+
85+
$this->assertEquals('{"prefixes":["example.com/one/","example.com/two/"]}', $request->getBody()->getContents());
86+
87+
return true;
88+
}
89+
),
90+
false
91+
);
92+
93+
$cloudflare->invalidateTags(['example.com/one/', 'example.com/two/']);
94+
}
95+
7496
public function testPurge(): void
7597
{
7698
$cloudflare = $this->getProxyClient();

0 commit comments

Comments
 (0)