Skip to content

Commit c19bdcf

Browse files
committed
fix custom ttl with symfony HttpCache to work regardless of s-maxage
1 parent 1f95522 commit c19bdcf

File tree

5 files changed

+38
-11
lines changed

5 files changed

+38
-11
lines changed

CHANGELOG.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,24 @@ Changelog
33

44
See also the [GitHub releases page](https://github.com/FriendsOfSymfony/FOSHttpCache/releases).
55

6-
2.16 (unreleased)
6+
2.16
77
----
88

9-
* Add flag `fallbackToSmaxage` to `CustomTtlListener` to allow controlling fallback to s-maxage if custom TTL header is not defined on the response.
10-
* Fix for Symfony HttpCache: Do not call store if Response object is not longer cacheable after event listeners. If you use the custom TTL system, this is only a performance improvement, because the TTL of the response would still be 0. With a custom listener that changes the response explicitly to not be cached but does not change s-maxage, this bug might have led to caching responses that should not have been cached
9+
### Symfony HttpCache
10+
11+
* Add events `PRE_FORWARD` and `POST_FORWARD` to allow event listeners to alter
12+
the request before and after it is sent to the backend.
13+
* Changed CustomTtlListener to use the `POST_FORWARD` event instead of
14+
`PRE_STORE`. Using PRE_STORE, requests that are not considered cacheable by
15+
Symfony were never cached, even when they had a custom TTL header.
16+
* Add flag `fallbackToSmaxage` to `CustomTtlListener` to allow controlling
17+
fallback to s-maxage if custom TTL header is not defined on the response.
18+
* Fix: Do not call store if Response object is not longer cacheable after event
19+
listeners. If you use the custom TTL system, this is only a performance
20+
improvement, because the TTL of the response would still be 0. With a custom
21+
listener that changes the response explicitly to not be cached but does not
22+
change s-maxage, this bug might have led to caching responses that should not
23+
have been cached.
1124

1225
2.15.3
1326
------

src/SymfonyCache/CustomTtlListener.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ public function useCustomTtl(CacheEvent $e)
7878
: 'false'
7979
;
8080
$response->headers->set(static::SMAXAGE_BACKUP, $backup);
81-
$response->setTtl(
82-
$response->headers->has($this->ttlHeader)
83-
? $response->headers->get($this->ttlHeader)
84-
: 0
81+
$response->headers->addCacheControlDirective(
82+
's-maxage',
83+
$response->headers->get($this->ttlHeader, 0)
8584
);
8685
}
8786

@@ -111,7 +110,7 @@ public function cleanResponse(CacheEvent $e)
111110
public static function getSubscribedEvents(): array
112111
{
113112
return [
114-
Events::PRE_STORE => 'useCustomTtl',
113+
Events::POST_FORWARD => 'useCustomTtl',
115114
Events::POST_HANDLE => 'cleanResponse',
116115
];
117116
}

src/SymfonyCache/EventDispatchingHttpCache.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ protected function invalidate(Request $request, $catch = false): Response
130130
return parent::invalidate($request, $catch);
131131
}
132132

133+
protected function forward(Request $request, bool $catch = false, ?Response $entry = null): Response
134+
{
135+
// do not abort early, if $entry is set this is a validation request
136+
$this->dispatch(Events::PRE_FORWARD, $request, $entry);
137+
138+
$response = parent::forward($request, $catch, $entry);
139+
140+
return $this->dispatch(Events::POST_FORWARD, $request, $response);
141+
}
142+
133143
/**
134144
* Dispatch an event if there are any listeners.
135145
*

src/SymfonyCache/Events.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ final class Events
2020

2121
public const POST_HANDLE = 'fos_http_cache.post_handle';
2222

23+
public const PRE_FORWARD = 'fos_http_cache.pre_forward';
24+
25+
public const POST_FORWARD = 'fos_http_cache.post_forward';
26+
2327
public const PRE_INVALIDATE = 'fos_http_cache.pre_invalidate';
2428

2529
public const PRE_STORE = 'fos_http_cache.pre_store';

tests/Functional/Symfony/EventDispatchingHttpCacheTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ public function testEventListeners()
4343

4444
$httpKernel = \Mockery::mock(HttpKernelInterface::class)
4545
->shouldReceive('handle')
46-
->withArgs([$request, HttpKernelInterface::MASTER_REQUEST, true])
4746
->andReturn($expectedResponse)
4847
->getMock();
4948
$store = \Mockery::mock(StoreInterface::class)
49+
->shouldReceive('lookup')->andReturn(null)->times(1)
50+
->shouldReceive('write')->times(1)
51+
->shouldReceive('unlock')->times(1)
5052
// need to declare the cleanup function explicitly to avoid issue between register_shutdown_function and mockery
51-
->shouldReceive('cleanup')
52-
->atMost(1)
53+
->shouldReceive('cleanup')->atMost(1)
5354
->getMock();
5455
$kernel = new AppCache($httpKernel, $store);
5556
$kernel->addSubscriber(new CustomTtlListener());

0 commit comments

Comments
 (0)