Skip to content

Commit ee0fb1a

Browse files
committed
adding after filter using kernel.response listener
1 parent 57d9c48 commit ee0fb1a

File tree

1 file changed

+70
-14
lines changed

1 file changed

+70
-14
lines changed

cookbook/event_dispatcher/before_after_filters.rst

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ token.
3030
in config and neither database setup nor authentication via
3131
the Security component will be used.
3232

33-
Creating a before filter with a controller.request event
34-
--------------------------------------------------------
33+
Adding a hash to a JSON Response
34+
--------------------------------
35+
36+
In the same context as the token example imagine that we want to add a sha1
37+
hash (with a salt using that token) to all our responses.
38+
39+
So, after generating a JSON response, this hash has to be added to the response.
40+
41+
Before and after filters with kernel.controller / kernel.response events
42+
------------------------------------------------------------------------
3543

3644
Basic Setup
3745
~~~~~~~~~~~
@@ -67,14 +75,18 @@ You can add basic token configuration using ``config.yml`` and the parameters ke
6775
));
6876
6977
Tag Controllers to be checked
70-
-----------------------------
78+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7179

7280
A ``kernel.controller`` listener gets notified on every request, right before
73-
the controller is executed. First, you need some way to identify if the controller
74-
that matches the request needs token validation.
81+
the controller is executed. Same happens to ``kernel.response`` listeners
82+
after the controller returns a Response object.
83+
84+
So, first, you need some way to identify if the controller that matches the
85+
request needs token validation. Regarding the response, you will also need
86+
some way to identify that the response needs to be hashed.
7587

7688
A clean and easy way is to create an empty interface and make the controllers
77-
implement it::
89+
implement it:
7890

7991
namespace Acme\DemoBundle\Controller;
8092

@@ -83,15 +95,33 @@ implement it::
8395
// Nothing here
8496
}
8597

98+
And also create a HashedResponse object extending Response
99+
100+
namespace Acme\DemoBundle\Response;
101+
102+
use Symfony\Component\HttpFoundation\Response;
103+
104+
class HashedResponse extends Response
105+
{
106+
// Nothing here
107+
}
108+
86109
A controller that implements this interface simply looks like this::
87110

111+
use Acme\DemoBundle\Controller\TokenAuthenticatedController;
112+
use Acme\DemoBundle\Response\HashedResponse;
113+
88114
class FooController implements TokenAuthenticatedController
89115
{
90-
// ... Your actions that need authentication
116+
// An action that needs authentication and signature
117+
public function barAction()
118+
{
119+
return new HashedResponse('Hello world');
120+
}
91121
}
92122

93123
Creating an Event Listener
94-
--------------------------
124+
~~~~~~~~~~~~~~~~~~~~~~~~~~
95125

96126
Next, you'll need to create an event listener, which will hold the logic
97127
that you want executed before your controllers. If you're not familiar with
@@ -101,10 +131,12 @@ event listeners, you can learn more about them at :doc:`/cookbook/service_contai
101131
namespace Acme\DemoBundle\EventListener;
102132

103133
use Acme\DemoBundle\Controller\TokenAuthenticatedController;
134+
use Acme\DemoBundle\Response\HashedResponse;
135+
104136
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
105137
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
106138

107-
class BeforeListener
139+
class BeforeAndAfterListener
108140
{
109141
private $tokens;
110142

@@ -132,14 +164,34 @@ event listeners, you can learn more about them at :doc:`/cookbook/service_contai
132164
}
133165
}
134166
}
167+
168+
public function onKernelResponse(FilterResponseEvent $event)
169+
{
170+
$response = $event->getResponse();
171+
172+
if ($response instanceof HashedResponse) {
173+
$token = $event->getRequest()->get('token');
174+
175+
$hash = sha1($response->getContent() . $token);
176+
177+
$response->setContent(
178+
json_encode(array(
179+
'hash' => $hash,
180+
'content' => $response->getContent(),
181+
))
182+
);
183+
}
184+
}
135185
}
136186

137187
Registering the Listener
138-
------------------------
188+
~~~~~~~~~~~~~~~~~~~~~~~~
139189

140190
Finally, register your listener as a service and tag it as an event listener.
141191
By listening on ``kernel.controller``, you're telling Symfony that you want
142-
your listener to be called just before any controller is executed:
192+
your listener to be called just before any controller is executed. And by
193+
listening on ``kernel.response``, your listener will be called after returning
194+
a Response:
143195

144196
.. configuration-block::
145197

@@ -148,25 +200,29 @@ your listener to be called just before any controller is executed:
148200
# app/config/config.yml (or inside your services.yml)
149201
services:
150202
demo.tokens.action_listener:
151-
class: Acme\DemoBundle\EventListener\BeforeListener
203+
class: Acme\DemoBundle\EventListener\BeforeAndAfterListener
152204
arguments: [ %tokens% ]
153205
tags:
154206
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
207+
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
155208
156209
.. code-block:: xml
157210
158211
<!-- app/config/config.xml (or inside your services.xml) -->
159-
<service id="demo.tokens.action_listener" class="Acme\DemoBundle\EventListener\BeforeListener">
212+
<service id="demo.tokens.action_listener" class="Acme\DemoBundle\EventListener\BeforeAndAfterListener">
160213
<argument>%tokens%</argument>
161214
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
215+
<tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
162216
</service>
163217
164218
.. code-block:: php
165219
166220
// app/config/config.php (or inside your services.php)
167221
use Symfony\Component\DependencyInjection\Definition;
168222
169-
$listener = new Definition('Acme\DemoBundle\EventListener\BeforeListener', array('%tokens%'));
223+
$listener = new Definition('Acme\DemoBundle\EventListener\BeforeAndAfterListener', array('%tokens%'));
170224
$listener->addTag('kernel.event_listener', array('event' => 'kernel.controller', 'method' => 'onKernelController'));
225+
$listener->addTag('kernel.event_listener', array('event' => 'kernel.response', 'method' => 'onKernelResponse'));
171226
$container->setDefinition('demo.tokens.action_listener', $listener);
172227
228+

0 commit comments

Comments
 (0)