Skip to content

Commit 7efe4bc

Browse files
committed
[HttpKernel] Add Kernel::terminate() and HttpKernel::terminate() for post-response logic
1 parent 7e2ca4a commit 7efe4bc

File tree

8 files changed

+121
-0
lines changed

8 files changed

+121
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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 Symfony\Component\HttpKernel\Event;
13+
14+
use Symfony\Component\HttpKernel\HttpKernelInterface;
15+
use Symfony\Component\EventDispatcher\Event;
16+
17+
/**
18+
* Allows to execute logic after a response was sent
19+
*
20+
* @author Jordi Boggiano <j.boggiano@seld.be>
21+
*/
22+
class PostResponseEvent extends Event
23+
{
24+
/**
25+
* The kernel in which this event was thrown
26+
* @var Symfony\Component\HttpKernel\HttpKernelInterface
27+
*/
28+
private $kernel;
29+
30+
public function __construct(HttpKernelInterface $kernel)
31+
{
32+
$this->kernel = $kernel;
33+
}
34+
35+
/**
36+
* Returns the kernel in which this event was thrown
37+
*
38+
* @return Symfony\Component\HttpKernel\HttpKernelInterface
39+
*/
40+
public function getKernel()
41+
{
42+
return $this->kernel;
43+
}
44+
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,18 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
215215
return $response;
216216
}
217217

218+
/**
219+
* Terminates a request/response cycle
220+
*
221+
* Should be called before shutdown, but after sending the response
222+
*
223+
* @api
224+
*/
225+
public function terminate()
226+
{
227+
$this->kernel->terminate();
228+
}
229+
218230
/**
219231
* Forwards the Request to the backend without storing the Response in the cache.
220232
*

src/Symfony/Component/HttpKernel/HttpKernel.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
1919
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
2020
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
21+
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
2122
use Symfony\Component\HttpFoundation\Request;
2223
use Symfony\Component\HttpFoundation\Response;
2324
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -78,6 +79,19 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
7879
}
7980
}
8081

82+
/**
83+
* Terminates a request/response cycle
84+
*
85+
* Should be called before shutdown, but after sending the response
86+
*
87+
* @api
88+
*/
89+
public function terminate()
90+
{
91+
$event = new PostResponseEvent($this);
92+
$this->dispatcher->dispatch(KernelEvents::TERMINATE, $event);
93+
}
94+
8195
/**
8296
* Handles a request to convert it to a response.
8397
*

src/Symfony/Component/HttpKernel/HttpKernelInterface.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ interface HttpKernelInterface
4444
* @api
4545
*/
4646
function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
47+
48+
/**
49+
* Terminates a request/response cycle
50+
*
51+
* Should be called after sending the response
52+
*/
53+
function terminate();
4754
}

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,22 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
171171
return $this->getHttpKernel()->handle($request, $type, $catch);
172172
}
173173

174+
/**
175+
* Terminates a request/response cycle
176+
*
177+
* Should be called before shutdown, but after sending the response
178+
*
179+
* @api
180+
*/
181+
public function terminate()
182+
{
183+
if (false === $this->booted) {
184+
throw new \LogicException('The kernel has been shutdown already');
185+
}
186+
187+
$this->getHttpKernel()->terminate();
188+
}
189+
174190
/**
175191
* Gets a http kernel from the container
176192
*

src/Symfony/Component/HttpKernel/KernelEvents.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,15 @@ final class KernelEvents
9191
* @api
9292
*/
9393
const RESPONSE = 'kernel.response';
94+
95+
/**
96+
* The TERMINATE event occurs once a reponse was sent
97+
*
98+
* This event allows you to run expensive post-response jobs.
99+
* The event listener method receives a
100+
* Symfony\Component\HttpKernel\Event\PostResponseEvent instance.
101+
*
102+
* @var string
103+
*/
104+
const TERMINATE = 'kernel.terminate';
94105
}

tests/Symfony/Tests/Component/HttpKernel/EventListener/ExceptionListenerTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
114114
return new Response('foo');
115115
}
116116

117+
public function terminate() {}
117118
}
118119

119120
class TestKernelThatThrowsException implements HttpKernelInterface
@@ -122,4 +123,6 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
122123
{
123124
throw new \Exception('bar');
124125
}
126+
127+
public function terminate() {}
125128
}

tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ public function testHandleWithAResponseListener()
164164
$this->assertEquals('foo', $kernel->handle(new Request())->getContent());
165165
}
166166

167+
public function testTerminate()
168+
{
169+
$dispatcher = new EventDispatcher();
170+
$kernel = new HttpKernel($dispatcher, $this->getResolver());
171+
$dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel) {
172+
$called = true;
173+
$capturedKernel = $event->getKernel();
174+
});
175+
176+
$kernel->terminate();
177+
$this->assertTrue($called);
178+
$this->assertEquals($kernel, $capturedKernel);
179+
}
180+
167181
protected function getResolver($controller = null)
168182
{
169183
if (null === $controller) {

0 commit comments

Comments
 (0)