Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit662eb17

Browse files
committed
[HttpCache] Do not call terminate() on cache hit
1 parent6597825 commit662eb17

File tree

4 files changed

+129
-7
lines changed

4 files changed

+129
-7
lines changed

‎src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
7878
* the cache can serve a stale response when an error is encountered (default: 60).
7979
* This setting is overridden by the stale-if-error HTTP Cache-Control extension
8080
* (see RFC 5861).
81+
*
82+
* * terminate_on_cache_hit Specifies if the kernel.terminate event should be dispatched even when the cache
83+
* was hit (default: true).
84+
* Unless your application needs to process events on cache hits, it is recommended
85+
* to set this to false to avoid having to bootstrap the Symfony framework on a cache hit.
8186
*/
8287
publicfunction__construct(HttpKernelInterface$kernel,StoreInterface$store,SurrogateInterface$surrogate =null,array$options = [])
8388
{
@@ -98,6 +103,7 @@ public function __construct(HttpKernelInterface $kernel, StoreInterface $store,
98103
'stale_if_error' =>60,
99104
'trace_level' =>'none',
100105
'trace_header' =>'X-Symfony-Cache',
106+
'terminate_on_cache_hit' =>true,
101107
],$options);
102108

103109
if (!isset($options['trace_level'])) {
@@ -238,6 +244,15 @@ public function handle(Request $request, int $type = HttpKernelInterface::MAIN_R
238244
*/
239245
publicfunctionterminate(Request$request,Response$response)
240246
{
247+
// Do not call any listeners in case of a cache hit.
248+
// This ensures identical behavior as if you had a separate
249+
// reverse caching proxy such as Varnish and the like.
250+
if ($this->options['terminate_on_cache_hit']) {
251+
trigger_deprecation('symfony/http-kernel','6.2','Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0.');
252+
}elseif (\in_array('fresh',$this->traces[$this->getTraceKey($request)] ?? [],true)) {
253+
return;
254+
}
255+
241256
if ($this->getKernel()instanceof TerminableInterface) {
242257
$this->getKernel()->terminate($request,$response);
243258
}

‎src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php‎

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111

1212
namespaceSymfony\Component\HttpKernel\Tests\HttpCache;
1313

14+
useSymfony\Bridge\PhpUnit\ExpectDeprecationTrait;
15+
useSymfony\Component\EventDispatcher\EventDispatcher;
1416
useSymfony\Component\HttpFoundation\Request;
1517
useSymfony\Component\HttpFoundation\Response;
18+
useSymfony\Component\HttpKernel\Event\TerminateEvent;
1619
useSymfony\Component\HttpKernel\HttpCache\Esi;
1720
useSymfony\Component\HttpKernel\HttpCache\HttpCache;
18-
useSymfony\Component\HttpKernel\HttpCache\Store;
1921
useSymfony\Component\HttpKernel\HttpCache\StoreInterface;
2022
useSymfony\Component\HttpKernel\HttpKernelInterface;
2123
useSymfony\Component\HttpKernel\Kernel;
@@ -25,6 +27,8 @@
2527
*/
2628
class HttpCacheTestextends HttpCacheTestCase
2729
{
30+
use ExpectDeprecationTrait;
31+
2832
publicfunctiontestTerminateDelegatesTerminationOnlyForTerminableInterface()
2933
{
3034
$storeMock =$this->getMockBuilder(StoreInterface::class)
@@ -33,7 +37,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
3337

3438
// does not implement TerminableInterface
3539
$kernel =newTestKernel();
36-
$httpCache =newHttpCache($kernel,$storeMock);
40+
$httpCache =newHttpCache($kernel,$storeMock,null, ['terminate_on_cache_hit' =>false]);
3741
$httpCache->terminate(Request::create('/'),newResponse());
3842

3943
$this->assertFalse($kernel->terminateCalled,'terminate() is never called if the kernel class does not implement TerminableInterface');
@@ -47,10 +51,108 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
4751
$kernelMock->expects($this->once())
4852
->method('terminate');
4953

50-
$kernel =newHttpCache($kernelMock,$storeMock);
54+
$kernel =newHttpCache($kernelMock,$storeMock,null, ['terminate_on_cache_hit' =>false]);
5155
$kernel->terminate(Request::create('/'),newResponse());
5256
}
5357

58+
publicfunctiontestDoesNotCallTerminateOnFreshResponse()
59+
{
60+
$terminateEvents = [];
61+
62+
$eventDispatcher =$this->createMock(EventDispatcher::class);
63+
$eventDispatcher
64+
->expects($this->any())
65+
->method('dispatch')
66+
->with($this->callback(function ($event)use (&$terminateEvents) {
67+
if ($eventinstanceof TerminateEvent) {
68+
$terminateEvents[] =$event;
69+
}
70+
71+
returntrue;
72+
}));
73+
74+
$this->setNextResponse(
75+
200,
76+
[
77+
'ETag' =>'1234',
78+
'Cache-Control' =>'public, s-maxage=60',
79+
],
80+
'Hello World',
81+
null,
82+
$eventDispatcher
83+
);
84+
85+
$this->request('GET','/');
86+
$this->assertHttpKernelIsCalled();
87+
$this->assertEquals(200,$this->response->getStatusCode());
88+
$this->assertTraceContains('miss');
89+
$this->assertTraceContains('store');
90+
$this->cache->terminate($this->request,$this->response);
91+
92+
sleep(2);
93+
94+
$this->request('GET','/');
95+
$this->assertHttpKernelIsNotCalled();
96+
$this->assertEquals(200,$this->response->getStatusCode());
97+
$this->assertTraceContains('fresh');
98+
$this->assertEquals(2,$this->response->headers->get('Age'));
99+
$this->cache->terminate($this->request,$this->response);
100+
101+
$this->assertCount(1,$terminateEvents);
102+
}
103+
104+
/**
105+
* @group legacy
106+
*/
107+
publicfunctiontestDoesCallTerminateOnFreshResponseIfConfigured()
108+
{
109+
$this->expectDeprecation('Since symfony/http-kernel 6.2: Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0.');
110+
111+
$terminateEvents = [];
112+
113+
$eventDispatcher =$this->createMock(EventDispatcher::class);
114+
$eventDispatcher
115+
->expects($this->any())
116+
->method('dispatch')
117+
->with($this->callback(function ($event)use (&$terminateEvents) {
118+
if ($eventinstanceof TerminateEvent) {
119+
$terminateEvents[] =$event;
120+
}
121+
122+
returntrue;
123+
}));
124+
125+
$this->setNextResponse(
126+
200,
127+
[
128+
'ETag' =>'1234',
129+
'Cache-Control' =>'public, s-maxage=60',
130+
],
131+
'Hello World',
132+
null,
133+
$eventDispatcher
134+
);
135+
$this->cacheConfig['terminate_on_cache_hit'] =true;
136+
137+
$this->request('GET','/');
138+
$this->assertHttpKernelIsCalled();
139+
$this->assertEquals(200,$this->response->getStatusCode());
140+
$this->assertTraceContains('miss');
141+
$this->assertTraceContains('store');
142+
$this->cache->terminate($this->request,$this->response);
143+
144+
sleep(2);
145+
146+
$this->request('GET','/');
147+
$this->assertHttpKernelIsNotCalled();
148+
$this->assertEquals(200,$this->response->getStatusCode());
149+
$this->assertTraceContains('fresh');
150+
$this->assertEquals(2,$this->response->headers->get('Age'));
151+
$this->cache->terminate($this->request,$this->response);
152+
153+
$this->assertCount(2,$terminateEvents);
154+
}
155+
54156
publicfunctiontestPassesOnNonGetHeadRequests()
55157
{
56158
$this->setNextResponse(200);

‎src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespaceSymfony\Component\HttpKernel\Tests\HttpCache;
1313

1414
usePHPUnit\Framework\TestCase;
15+
useSymfony\Component\EventDispatcher\EventDispatcher;
1516
useSymfony\Component\HttpFoundation\Request;
1617
useSymfony\Component\HttpKernel\HttpCache\Esi;
1718
useSymfony\Component\HttpKernel\HttpCache\HttpCache;
@@ -124,6 +125,10 @@ public function request($method, $uri = '/', $server = [], $cookies = [], $esi =
124125
$this->cacheConfig['debug'] =true;
125126
}
126127

128+
if (!isset($this->cacheConfig['terminate_on_cache_hit'])) {
129+
$this->cacheConfig['terminate_on_cache_hit'] =false;
130+
}
131+
127132
$this->esi =$esi ?newEsi() :null;
128133
$this->cache =newHttpCache($this->kernel,$this->store,$this->esi,$this->cacheConfig);
129134
$this->request = Request::create($uri,$method, [],$cookies, [],$server);
@@ -145,9 +150,9 @@ public function getMetaStorageValues()
145150
}
146151

147152
// A basic response with 200 status code and a tiny body.
148-
publicfunctionsetNextResponse($statusCode =200,array$headers = [],$body ='Hello World',\Closure$customizer =null)
153+
publicfunctionsetNextResponse($statusCode =200,array$headers = [],$body ='Hello World',\Closure$customizer =null,EventDispatcher$eventDispatcher =null)
149154
{
150-
$this->kernel =newTestHttpKernel($body,$statusCode,$headers,$customizer);
155+
$this->kernel =newTestHttpKernel($body,$statusCode,$headers,$customizer,$eventDispatcher);
151156
}
152157

153158
publicfunctionsetNextResponses($responses)

‎src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ class TestHttpKernel extends HttpKernel implements ControllerResolverInterface,
2929
protected$catch =false;
3030
protected$backendRequest;
3131

32-
publicfunction__construct($body,$status,$headers,\Closure$customizer =null)
32+
publicfunction__construct($body,$status,$headers,\Closure$customizer =null,EventDispatcher$eventDispatcher =null)
3333
{
3434
$this->body =$body;
3535
$this->status =$status;
3636
$this->headers =$headers;
3737
$this->customizer =$customizer;
3838

39-
parent::__construct(newEventDispatcher(),$this,null,$this,true);
39+
parent::__construct($eventDispatcher ??newEventDispatcher(),$this,null,$this,true);
4040
}
4141

4242
publicfunctionassert(\Closure$callback)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp