1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the FOSHttpCacheBundle 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\HttpCacheBundle\Tests\Unit\EventListener; |
13
|
|
|
|
14
|
|
|
use FOS\HttpCacheBundle\EventListener\UserContextSubscriber; |
15
|
|
|
use Symfony\Component\HttpFoundation\Request; |
16
|
|
|
use Symfony\Component\HttpFoundation\Response; |
17
|
|
|
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; |
18
|
|
|
use Symfony\Component\HttpKernel\Event\GetResponseEvent; |
19
|
|
|
use Symfony\Component\HttpKernel\HttpKernelInterface; |
20
|
|
|
use Symfony\Component\Routing\Matcher\RequestMatcherInterface; |
21
|
|
|
|
22
|
|
|
class UserContextSubscriberTest extends \PHPUnit_Framework_TestCase |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @expectedException \InvalidArgumentException |
26
|
|
|
*/ |
27
|
|
|
public function testMisconfiguration() |
28
|
|
|
{ |
29
|
|
|
new UserContextSubscriber( |
30
|
|
|
\Mockery::mock('\Symfony\Component\HttpFoundation\RequestMatcherInterface'), |
31
|
|
|
\Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'), |
32
|
|
|
array() |
33
|
|
|
); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
View Code Duplication |
public function testOnKernelRequest() |
|
|
|
|
37
|
|
|
{ |
38
|
|
|
$request = new Request(); |
39
|
|
|
$request->setMethod('HEAD'); |
40
|
|
|
|
41
|
|
|
$requestMatcher = $this->getRequestMatcher($request, true); |
42
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
43
|
|
|
$hashGenerator->shouldReceive('generateHash')->andReturn('hash'); |
44
|
|
|
|
45
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
46
|
|
|
$event = $this->getKernelRequestEvent($request); |
47
|
|
|
|
48
|
|
|
$userContextSubscriber->onKernelRequest($event); |
49
|
|
|
|
50
|
|
|
$response = $event->getResponse(); |
51
|
|
|
|
52
|
|
|
$this->assertNotNull($response); |
53
|
|
|
$this->assertInstanceOf('\Symfony\Component\HttpFoundation\Response', $response); |
54
|
|
|
$this->assertEquals('hash', $response->headers->get('X-Hash')); |
55
|
|
|
$this->assertNull($response->headers->get('Vary')); |
56
|
|
|
$this->assertEquals('max-age=0, no-cache, private', $response->headers->get('Cache-Control')); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
View Code Duplication |
public function testOnKernelRequestNonMaster() |
|
|
|
|
60
|
|
|
{ |
61
|
|
|
$request = new Request(); |
62
|
|
|
$request->setMethod('HEAD'); |
63
|
|
|
|
64
|
|
|
$requestMatcher = $this->getRequestMatcher($request, true); |
65
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
66
|
|
|
$hashGenerator->shouldReceive('generateHash')->never(); |
67
|
|
|
|
68
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
69
|
|
|
$event = $this->getKernelRequestEvent($request, HttpKernelInterface::SUB_REQUEST); |
70
|
|
|
|
71
|
|
|
$userContextSubscriber->onKernelRequest($event); |
72
|
|
|
|
73
|
|
|
$this->assertNull($event->getResponse()); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
View Code Duplication |
public function testOnKernelRequestCached() |
|
|
|
|
77
|
|
|
{ |
78
|
|
|
$request = new Request(); |
79
|
|
|
$request->setMethod('HEAD'); |
80
|
|
|
|
81
|
|
|
$requestMatcher = $this->getRequestMatcher($request, true); |
82
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
83
|
|
|
$hashGenerator->shouldReceive('generateHash')->andReturn('hash'); |
84
|
|
|
|
85
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash', 30); |
|
|
|
|
86
|
|
|
$event = $this->getKernelRequestEvent($request); |
87
|
|
|
|
88
|
|
|
$userContextSubscriber->onKernelRequest($event); |
89
|
|
|
|
90
|
|
|
$response = $event->getResponse(); |
91
|
|
|
|
92
|
|
|
$this->assertNotNull($response); |
93
|
|
|
$this->assertInstanceOf('\Symfony\Component\HttpFoundation\Response', $response); |
94
|
|
|
$this->assertEquals('hash', $response->headers->get('X-Hash')); |
95
|
|
|
$this->assertEquals('X-SessionId', $response->headers->get('Vary')); |
96
|
|
|
$this->assertEquals('max-age=30, public', $response->headers->get('Cache-Control')); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
View Code Duplication |
public function testOnKernelRequestNotMatched() |
|
|
|
|
100
|
|
|
{ |
101
|
|
|
$request = new Request(); |
102
|
|
|
$request->setMethod('HEAD'); |
103
|
|
|
|
104
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
105
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
106
|
|
|
$hashGenerator->shouldReceive('generateHash')->andReturn('hash'); |
107
|
|
|
|
108
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
109
|
|
|
$event = $this->getKernelRequestEvent($request); |
110
|
|
|
|
111
|
|
|
$userContextSubscriber->onKernelRequest($event); |
112
|
|
|
|
113
|
|
|
$response = $event->getResponse(); |
114
|
|
|
|
115
|
|
|
$this->assertNull($response); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
public function testOnKernelResponse() |
119
|
|
|
{ |
120
|
|
|
$request = new Request(); |
121
|
|
|
$request->setMethod('HEAD'); |
122
|
|
|
$request->headers->set('X-Hash', 'hash'); |
123
|
|
|
|
124
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
125
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
126
|
|
|
|
127
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
128
|
|
|
$event = $this->getKernelResponseEvent($request); |
129
|
|
|
|
130
|
|
|
$userContextSubscriber->onKernelResponse($event); |
131
|
|
|
|
132
|
|
|
$this->assertTrue($event->getResponse()->headers->has('Vary'), 'Vary header must be set'); |
133
|
|
|
$this->assertContains('X-Hash', $event->getResponse()->headers->get('Vary')); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
View Code Duplication |
public function testOnKernelResponseNotMaster() |
|
|
|
|
137
|
|
|
{ |
138
|
|
|
$request = new Request(); |
139
|
|
|
$request->setMethod('HEAD'); |
140
|
|
|
$request->headers->set('X-Hash', 'hash'); |
141
|
|
|
|
142
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
143
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
144
|
|
|
|
145
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
146
|
|
|
$event = $this->getKernelResponseEvent($request, null, HttpKernelInterface::SUB_REQUEST); |
147
|
|
|
|
148
|
|
|
$userContextSubscriber->onKernelResponse($event); |
149
|
|
|
|
150
|
|
|
$this->assertFalse($event->getResponse()->headers->has('Vary')); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* If there is no hash in the request, vary on the user identifier. |
155
|
|
|
*/ |
156
|
|
View Code Duplication |
public function testOnKernelResponseNotCached() |
|
|
|
|
157
|
|
|
{ |
158
|
|
|
$request = new Request(); |
159
|
|
|
$request->setMethod('HEAD'); |
160
|
|
|
|
161
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
162
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
163
|
|
|
|
164
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
165
|
|
|
$event = $this->getKernelResponseEvent($request); |
166
|
|
|
|
167
|
|
|
$userContextSubscriber->onKernelResponse($event); |
168
|
|
|
|
169
|
|
|
$this->assertEquals('X-SessionId', $event->getResponse()->headers->get('Vary')); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* If there is no hash in the request, vary on the user identifier. |
174
|
|
|
*/ |
175
|
|
|
public function testFullRequestHashOk() |
176
|
|
|
{ |
177
|
|
|
$request = new Request(); |
178
|
|
|
$request->setMethod('GET'); |
179
|
|
|
$request->headers->set('X-Hash', 'hash'); |
180
|
|
|
|
181
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
182
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
183
|
|
|
$hashGenerator->shouldReceive('generateHash')->andReturn('hash'); |
184
|
|
|
|
185
|
|
|
// onKernelRequest |
186
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
187
|
|
|
$event = $this->getKernelRequestEvent($request); |
188
|
|
|
|
189
|
|
|
$userContextSubscriber->onKernelRequest($event); |
190
|
|
|
|
191
|
|
|
$response = $event->getResponse(); |
192
|
|
|
|
193
|
|
|
$this->assertNull($response); |
194
|
|
|
|
195
|
|
|
// onKernelResponse |
196
|
|
|
$event = $this->getKernelResponseEvent($request); |
197
|
|
|
$userContextSubscriber->onKernelResponse($event); |
198
|
|
|
|
199
|
|
|
$this->assertContains('X-Hash', $event->getResponse()->headers->get('Vary')); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* If the request is an anonymous one, no hash should be generated/validated. |
204
|
|
|
*/ |
205
|
|
|
public function testFullAnonymousRequestHashNotGenerated() |
206
|
|
|
{ |
207
|
|
|
$request = new Request(); |
208
|
|
|
$request->setMethod('GET'); |
209
|
|
|
$request->headers->set('X-Hash', 'anonymous-hash'); |
210
|
|
|
|
211
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
212
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
213
|
|
|
$hashGenerator->shouldReceive('generateHash')->never(); |
214
|
|
|
|
215
|
|
|
$anonymousRequestMatcher = \Mockery::mock('\Symfony\Component\HttpFoundation\RequestMatcherInterface'); |
216
|
|
|
$anonymousRequestMatcher->shouldReceive('matches')->andReturn(true); |
217
|
|
|
|
218
|
|
|
// onKernelRequest |
219
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash', 0, true, $anonymousRequestMatcher); |
|
|
|
|
220
|
|
|
$event = $this->getKernelRequestEvent($request); |
221
|
|
|
|
222
|
|
|
$userContextSubscriber->onKernelRequest($event); |
223
|
|
|
|
224
|
|
|
$response = $event->getResponse(); |
225
|
|
|
|
226
|
|
|
$this->assertNull($response); |
227
|
|
|
|
228
|
|
|
// onKernelResponse |
229
|
|
|
$event = $this->getKernelResponseEvent($request); |
230
|
|
|
$userContextSubscriber->onKernelResponse($event); |
231
|
|
|
|
232
|
|
|
$this->assertContains('X-Hash', $event->getResponse()->headers->get('Vary')); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* If there is no hash in the requests but session changed, prevent setting bad cache. |
237
|
|
|
*/ |
238
|
|
|
public function testFullRequestHashChanged() |
239
|
|
|
{ |
240
|
|
|
$request = new Request(); |
241
|
|
|
$request->setMethod('GET'); |
242
|
|
|
$request->headers->set('X-Hash', 'hash'); |
243
|
|
|
|
244
|
|
|
$requestMatcher = $this->getRequestMatcher($request, false); |
245
|
|
|
$hashGenerator = \Mockery::mock('\FOS\HttpCache\UserContext\HashGenerator'); |
246
|
|
|
$hashGenerator->shouldReceive('generateHash')->andReturn('hash-changed'); |
247
|
|
|
|
248
|
|
|
// onKernelRequest |
249
|
|
|
$userContextSubscriber = new UserContextSubscriber($requestMatcher, $hashGenerator, array('X-SessionId'), 'X-Hash'); |
|
|
|
|
250
|
|
|
$event = $this->getKernelRequestEvent($request); |
251
|
|
|
|
252
|
|
|
$userContextSubscriber->onKernelRequest($event); |
253
|
|
|
|
254
|
|
|
$response = $event->getResponse(); |
255
|
|
|
|
256
|
|
|
$this->assertNull($response); |
257
|
|
|
|
258
|
|
|
// onKernelResponse |
259
|
|
|
$event = $this->getKernelResponseEvent($request); |
260
|
|
|
$userContextSubscriber->onKernelResponse($event); |
261
|
|
|
|
262
|
|
|
$this->assertFalse($event->getResponse()->headers->has('Vary')); |
263
|
|
|
$this->assertEquals('max-age=0, no-cache, private', $event->getResponse()->headers->get('Cache-Control')); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
protected function getKernelRequestEvent(Request $request, $type = HttpKernelInterface::MASTER_REQUEST) |
267
|
|
|
{ |
268
|
|
|
return new GetResponseEvent( |
269
|
|
|
\Mockery::mock('\Symfony\Component\HttpKernel\HttpKernelInterface'), |
270
|
|
|
$request, |
271
|
|
|
$type |
272
|
|
|
); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
View Code Duplication |
protected function getKernelResponseEvent(Request $request, Response $response = null, $type = HttpKernelInterface::MASTER_REQUEST) |
|
|
|
|
276
|
|
|
{ |
277
|
|
|
return new FilterResponseEvent( |
278
|
|
|
\Mockery::mock('\Symfony\Component\HttpKernel\HttpKernelInterface'), |
279
|
|
|
$request, |
280
|
|
|
$type, |
281
|
|
|
$response ?: new Response() |
282
|
|
|
); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* @param Request $request |
287
|
|
|
* @param bool $match |
288
|
|
|
* |
289
|
|
|
* @return \Mockery\MockInterface|RequestMatcherInterface |
290
|
|
|
*/ |
291
|
|
|
private function getRequestMatcher(Request $request, $match) |
292
|
|
|
{ |
293
|
|
|
$requestMatcher = \Mockery::mock('\Symfony\Component\HttpFoundation\RequestMatcherInterface'); |
294
|
|
|
$requestMatcher->shouldReceive('matches')->with($request)->andReturn($match); |
295
|
|
|
|
296
|
|
|
return $requestMatcher; |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.