4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpFoundation\Tests;
14 use Symfony\Component\HttpFoundation\Request;
15 use Symfony\Component\HttpFoundation\Response;
18 * @group time-sensitive
20 class ResponseTest extends ResponseTestCase
22 public function testCreate()
24 $response = Response::create('foo', 301, array('Foo' => 'bar'));
26 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
27 $this->assertEquals(301, $response->getStatusCode());
28 $this->assertEquals('bar', $response->headers->get('foo'));
31 public function testToString()
33 $response = new Response();
34 $response = explode("\r\n", $response);
35 $this->assertEquals('HTTP/1.0 200 OK', $response[0]);
36 $this->assertEquals('Cache-Control: no-cache, private', $response[1]);
39 public function testClone()
41 $response = new Response();
42 $responseClone = clone $response;
43 $this->assertEquals($response, $responseClone);
46 public function testSendHeaders()
48 $response = new Response();
49 $headers = $response->sendHeaders();
50 $this->assertObjectHasAttribute('headers', $headers);
51 $this->assertObjectHasAttribute('content', $headers);
52 $this->assertObjectHasAttribute('version', $headers);
53 $this->assertObjectHasAttribute('statusCode', $headers);
54 $this->assertObjectHasAttribute('statusText', $headers);
55 $this->assertObjectHasAttribute('charset', $headers);
58 public function testSend()
60 $response = new Response();
61 $responseSend = $response->send();
62 $this->assertObjectHasAttribute('headers', $responseSend);
63 $this->assertObjectHasAttribute('content', $responseSend);
64 $this->assertObjectHasAttribute('version', $responseSend);
65 $this->assertObjectHasAttribute('statusCode', $responseSend);
66 $this->assertObjectHasAttribute('statusText', $responseSend);
67 $this->assertObjectHasAttribute('charset', $responseSend);
70 public function testGetCharset()
72 $response = new Response();
73 $charsetOrigin = 'UTF-8';
74 $response->setCharset($charsetOrigin);
75 $charset = $response->getCharset();
76 $this->assertEquals($charsetOrigin, $charset);
79 public function testIsCacheable()
81 $response = new Response();
82 $this->assertFalse($response->isCacheable());
85 public function testIsCacheableWithErrorCode()
87 $response = new Response('', 500);
88 $this->assertFalse($response->isCacheable());
91 public function testIsCacheableWithNoStoreDirective()
93 $response = new Response();
94 $response->headers->set('cache-control', 'private');
95 $this->assertFalse($response->isCacheable());
98 public function testIsCacheableWithSetTtl()
100 $response = new Response();
101 $response->setTtl(10);
102 $this->assertTrue($response->isCacheable());
105 public function testMustRevalidate()
107 $response = new Response();
108 $this->assertFalse($response->mustRevalidate());
111 public function testMustRevalidateWithMustRevalidateCacheControlHeader()
113 $response = new Response();
114 $response->headers->set('cache-control', 'must-revalidate');
116 $this->assertTrue($response->mustRevalidate());
119 public function testMustRevalidateWithProxyRevalidateCacheControlHeader()
121 $response = new Response();
122 $response->headers->set('cache-control', 'proxy-revalidate');
124 $this->assertTrue($response->mustRevalidate());
127 public function testSetNotModified()
129 $response = new Response('foo');
130 $modified = $response->setNotModified();
131 $this->assertObjectHasAttribute('headers', $modified);
132 $this->assertObjectHasAttribute('content', $modified);
133 $this->assertObjectHasAttribute('version', $modified);
134 $this->assertObjectHasAttribute('statusCode', $modified);
135 $this->assertObjectHasAttribute('statusText', $modified);
136 $this->assertObjectHasAttribute('charset', $modified);
137 $this->assertEquals(304, $modified->getStatusCode());
140 $modified->sendContent();
141 $string = ob_get_clean();
142 $this->assertEmpty($string);
145 public function testIsSuccessful()
147 $response = new Response();
148 $this->assertTrue($response->isSuccessful());
151 public function testIsNotModified()
153 $response = new Response();
154 $modified = $response->isNotModified(new Request());
155 $this->assertFalse($modified);
158 public function testIsNotModifiedNotSafe()
160 $request = Request::create('/homepage', 'POST');
162 $response = new Response();
163 $this->assertFalse($response->isNotModified($request));
166 public function testIsNotModifiedLastModified()
168 $before = 'Sun, 25 Aug 2013 18:32:31 GMT';
169 $modified = 'Sun, 25 Aug 2013 18:33:31 GMT';
170 $after = 'Sun, 25 Aug 2013 19:33:31 GMT';
172 $request = new Request();
173 $request->headers->set('If-Modified-Since', $modified);
175 $response = new Response();
177 $response->headers->set('Last-Modified', $modified);
178 $this->assertTrue($response->isNotModified($request));
180 $response->headers->set('Last-Modified', $before);
181 $this->assertTrue($response->isNotModified($request));
183 $response->headers->set('Last-Modified', $after);
184 $this->assertFalse($response->isNotModified($request));
186 $response->headers->set('Last-Modified', '');
187 $this->assertFalse($response->isNotModified($request));
190 public function testIsNotModifiedEtag()
192 $etagOne = 'randomly_generated_etag';
193 $etagTwo = 'randomly_generated_etag_2';
195 $request = new Request();
196 $request->headers->set('if_none_match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree'));
198 $response = new Response();
200 $response->headers->set('ETag', $etagOne);
201 $this->assertTrue($response->isNotModified($request));
203 $response->headers->set('ETag', $etagTwo);
204 $this->assertTrue($response->isNotModified($request));
206 $response->headers->set('ETag', '');
207 $this->assertFalse($response->isNotModified($request));
210 public function testIsNotModifiedLastModifiedAndEtag()
212 $before = 'Sun, 25 Aug 2013 18:32:31 GMT';
213 $modified = 'Sun, 25 Aug 2013 18:33:31 GMT';
214 $after = 'Sun, 25 Aug 2013 19:33:31 GMT';
215 $etag = 'randomly_generated_etag';
217 $request = new Request();
218 $request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree'));
219 $request->headers->set('If-Modified-Since', $modified);
221 $response = new Response();
223 $response->headers->set('ETag', $etag);
224 $response->headers->set('Last-Modified', $after);
225 $this->assertFalse($response->isNotModified($request));
227 $response->headers->set('ETag', 'non-existent-etag');
228 $response->headers->set('Last-Modified', $before);
229 $this->assertFalse($response->isNotModified($request));
231 $response->headers->set('ETag', $etag);
232 $response->headers->set('Last-Modified', $modified);
233 $this->assertTrue($response->isNotModified($request));
236 public function testIsNotModifiedIfModifiedSinceAndEtagWithoutLastModified()
238 $modified = 'Sun, 25 Aug 2013 18:33:31 GMT';
239 $etag = 'randomly_generated_etag';
241 $request = new Request();
242 $request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree'));
243 $request->headers->set('If-Modified-Since', $modified);
245 $response = new Response();
247 $response->headers->set('ETag', $etag);
248 $this->assertTrue($response->isNotModified($request));
250 $response->headers->set('ETag', 'non-existent-etag');
251 $this->assertFalse($response->isNotModified($request));
254 public function testIsValidateable()
256 $response = new Response('', 200, array('Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
257 $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if Last-Modified is present');
259 $response = new Response('', 200, array('ETag' => '"12345"'));
260 $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if ETag is present');
262 $response = new Response();
263 $this->assertFalse($response->isValidateable(), '->isValidateable() returns false when no validator is present');
266 public function testGetDate()
268 $oneHourAgo = $this->createDateTimeOneHourAgo();
269 $response = new Response('', 200, array('Date' => $oneHourAgo->format(DATE_RFC2822)));
270 $date = $response->getDate();
271 $this->assertEquals($oneHourAgo->getTimestamp(), $date->getTimestamp(), '->getDate() returns the Date header if present');
273 $response = new Response();
274 $date = $response->getDate();
275 $this->assertEquals(time(), $date->getTimestamp(), '->getDate() returns the current Date if no Date header present');
277 $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
278 $now = $this->createDateTimeNow();
279 $response->headers->set('Date', $now->format(DATE_RFC2822));
280 $date = $response->getDate();
281 $this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the date when the header has been modified');
283 $response = new Response('', 200);
284 $now = $this->createDateTimeNow();
285 $response->headers->remove('Date');
286 $date = $response->getDate();
287 $this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the current Date when the header has previously been removed');
290 public function testGetMaxAge()
292 $response = new Response();
293 $response->headers->set('Cache-Control', 's-maxage=600, max-age=0');
294 $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() uses s-maxage cache control directive when present');
296 $response = new Response();
297 $response->headers->set('Cache-Control', 'max-age=600');
298 $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() falls back to max-age when no s-maxage directive present');
300 $response = new Response();
301 $response->headers->set('Cache-Control', 'must-revalidate');
302 $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
303 $this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present');
305 $response = new Response();
306 $response->headers->set('Cache-Control', 'must-revalidate');
307 $response->headers->set('Expires', -1);
308 $this->assertEquals('Sat, 01 Jan 00 00:00:00 +0000', $response->getExpires()->format(DATE_RFC822));
310 $response = new Response();
311 $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available');
314 public function testSetSharedMaxAge()
316 $response = new Response();
317 $response->setSharedMaxAge(20);
319 $cacheControl = $response->headers->get('Cache-Control');
320 $this->assertEquals('public, s-maxage=20', $cacheControl);
323 public function testIsPrivate()
325 $response = new Response();
326 $response->headers->set('Cache-Control', 'max-age=100');
327 $response->setPrivate();
328 $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true');
329 $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true');
331 $response = new Response();
332 $response->headers->set('Cache-Control', 'public, max-age=100');
333 $response->setPrivate();
334 $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true');
335 $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true');
336 $this->assertFalse($response->headers->hasCacheControlDirective('public'), '->isPrivate() removes the public Cache-Control directive');
339 public function testExpire()
341 $response = new Response();
342 $response->headers->set('Cache-Control', 'max-age=100');
344 $this->assertEquals(100, $response->headers->get('Age'), '->expire() sets the Age to max-age when present');
346 $response = new Response();
347 $response->headers->set('Cache-Control', 'max-age=100, s-maxage=500');
349 $this->assertEquals(500, $response->headers->get('Age'), '->expire() sets the Age to s-maxage when both max-age and s-maxage are present');
351 $response = new Response();
352 $response->headers->set('Cache-Control', 'max-age=5, s-maxage=500');
353 $response->headers->set('Age', '1000');
355 $this->assertEquals(1000, $response->headers->get('Age'), '->expire() does nothing when the response is already stale/expired');
357 $response = new Response();
359 $this->assertFalse($response->headers->has('Age'), '->expire() does nothing when the response does not include freshness information');
361 $response = new Response();
362 $response->headers->set('Expires', -1);
364 $this->assertNull($response->headers->get('Age'), '->expire() does not set the Age when the response is expired');
366 $response = new Response();
367 $response->headers->set('Expires', date(DATE_RFC2822, time() + 600));
369 $this->assertNull($response->headers->get('Expires'), '->expire() removes the Expires header when the response is fresh');
372 public function testGetTtl()
374 $response = new Response();
375 $this->assertNull($response->getTtl(), '->getTtl() returns null when no Expires or Cache-Control headers are present');
377 $response = new Response();
378 $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
379 $this->assertEquals(3600, $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present');
381 $response = new Response();
382 $response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(DATE_RFC2822));
383 $this->assertLessThan(0, $response->getTtl(), '->getTtl() returns negative values when Expires is in past');
385 $response = new Response();
386 $response->headers->set('Expires', $response->getDate()->format(DATE_RFC2822));
387 $response->headers->set('Age', 0);
388 $this->assertSame(0, $response->getTtl(), '->getTtl() correctly handles zero');
390 $response = new Response();
391 $response->headers->set('Cache-Control', 'max-age=60');
392 $this->assertEquals(60, $response->getTtl(), '->getTtl() uses Cache-Control max-age when present');
395 public function testSetClientTtl()
397 $response = new Response();
398 $response->setClientTtl(10);
400 $this->assertEquals($response->getMaxAge(), $response->getAge() + 10);
403 public function testGetSetProtocolVersion()
405 $response = new Response();
407 $this->assertEquals('1.0', $response->getProtocolVersion());
409 $response->setProtocolVersion('1.1');
411 $this->assertEquals('1.1', $response->getProtocolVersion());
414 public function testGetVary()
416 $response = new Response();
417 $this->assertEquals(array(), $response->getVary(), '->getVary() returns an empty array if no Vary header is present');
419 $response = new Response();
420 $response->headers->set('Vary', 'Accept-Language');
421 $this->assertEquals(array('Accept-Language'), $response->getVary(), '->getVary() parses a single header name value');
423 $response = new Response();
424 $response->headers->set('Vary', 'Accept-Language User-Agent X-Foo');
425 $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by spaces');
427 $response = new Response();
428 $response->headers->set('Vary', 'Accept-Language,User-Agent, X-Foo');
429 $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by commas');
431 $vary = array('Accept-Language', 'User-Agent', 'X-foo');
433 $response = new Response();
434 $response->headers->set('Vary', $vary);
435 $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays');
437 $response = new Response();
438 $response->headers->set('Vary', 'Accept-Language, User-Agent, X-foo');
439 $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays');
442 public function testSetVary()
444 $response = new Response();
445 $response->setVary('Accept-Language');
446 $this->assertEquals(array('Accept-Language'), $response->getVary());
448 $response->setVary('Accept-Language, User-Agent');
449 $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() replace the vary header by default');
451 $response->setVary('X-Foo', false);
452 $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->setVary() doesn\'t wipe out earlier Vary headers if replace is set to false');
455 public function testDefaultContentType()
457 $headerMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\ResponseHeaderBag')->setMethods(array('set'))->getMock();
458 $headerMock->expects($this->at(0))
460 ->with('Content-Type', 'text/html');
461 $headerMock->expects($this->at(1))
463 ->with('Content-Type', 'text/html; charset=UTF-8');
465 $response = new Response('foo');
466 $response->headers = $headerMock;
468 $response->prepare(new Request());
471 public function testContentTypeCharset()
473 $response = new Response();
474 $response->headers->set('Content-Type', 'text/css');
476 // force fixContentType() to be called
477 $response->prepare(new Request());
479 $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type'));
482 public function testPrepareDoesNothingIfContentTypeIsSet()
484 $response = new Response('foo');
485 $response->headers->set('Content-Type', 'text/plain');
487 $response->prepare(new Request());
489 $this->assertEquals('text/plain; charset=UTF-8', $response->headers->get('content-type'));
492 public function testPrepareDoesNothingIfRequestFormatIsNotDefined()
494 $response = new Response('foo');
496 $response->prepare(new Request());
498 $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type'));
501 public function testPrepareSetContentType()
503 $response = new Response('foo');
504 $request = Request::create('/');
505 $request->setRequestFormat('json');
507 $response->prepare($request);
509 $this->assertEquals('application/json', $response->headers->get('content-type'));
512 public function testPrepareRemovesContentForHeadRequests()
514 $response = new Response('foo');
515 $request = Request::create('/', 'HEAD');
518 $response->headers->set('Content-Length', $length);
519 $response->prepare($request);
521 $this->assertEquals('', $response->getContent());
522 $this->assertEquals($length, $response->headers->get('Content-Length'), 'Content-Length should be as if it was GET; see RFC2616 14.13');
525 public function testPrepareRemovesContentForInformationalResponse()
527 $response = new Response('foo');
528 $request = Request::create('/');
530 $response->setContent('content');
531 $response->setStatusCode(101);
532 $response->prepare($request);
533 $this->assertEquals('', $response->getContent());
534 $this->assertFalse($response->headers->has('Content-Type'));
535 $this->assertFalse($response->headers->has('Content-Type'));
537 $response->setContent('content');
538 $response->setStatusCode(304);
539 $response->prepare($request);
540 $this->assertEquals('', $response->getContent());
541 $this->assertFalse($response->headers->has('Content-Type'));
542 $this->assertFalse($response->headers->has('Content-Length'));
545 public function testPrepareRemovesContentLength()
547 $response = new Response('foo');
548 $request = Request::create('/');
550 $response->headers->set('Content-Length', 12345);
551 $response->prepare($request);
552 $this->assertEquals(12345, $response->headers->get('Content-Length'));
554 $response->headers->set('Transfer-Encoding', 'chunked');
555 $response->prepare($request);
556 $this->assertFalse($response->headers->has('Content-Length'));
559 public function testPrepareSetsPragmaOnHttp10Only()
561 $request = Request::create('/', 'GET');
562 $request->server->set('SERVER_PROTOCOL', 'HTTP/1.0');
564 $response = new Response('foo');
565 $response->prepare($request);
566 $this->assertEquals('no-cache', $response->headers->get('pragma'));
567 $this->assertEquals('-1', $response->headers->get('expires'));
569 $request->server->set('SERVER_PROTOCOL', 'HTTP/1.1');
570 $response = new Response('foo');
571 $response->prepare($request);
572 $this->assertFalse($response->headers->has('pragma'));
573 $this->assertFalse($response->headers->has('expires'));
576 public function testSetCache()
578 $response = new Response();
579 //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public')
581 $response->setCache(array('wrong option' => 'value'));
582 $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported');
583 } catch (\Exception $e) {
584 $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported');
585 $this->assertContains('"wrong option"', $e->getMessage());
588 $options = array('etag' => '"whatever"');
589 $response->setCache($options);
590 $this->assertEquals($response->getEtag(), '"whatever"');
592 $now = $this->createDateTimeNow();
593 $options = array('last_modified' => $now);
594 $response->setCache($options);
595 $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp());
597 $options = array('max_age' => 100);
598 $response->setCache($options);
599 $this->assertEquals($response->getMaxAge(), 100);
601 $options = array('s_maxage' => 200);
602 $response->setCache($options);
603 $this->assertEquals($response->getMaxAge(), 200);
605 $this->assertTrue($response->headers->hasCacheControlDirective('public'));
606 $this->assertFalse($response->headers->hasCacheControlDirective('private'));
608 $response->setCache(array('public' => true));
609 $this->assertTrue($response->headers->hasCacheControlDirective('public'));
610 $this->assertFalse($response->headers->hasCacheControlDirective('private'));
612 $response->setCache(array('public' => false));
613 $this->assertFalse($response->headers->hasCacheControlDirective('public'));
614 $this->assertTrue($response->headers->hasCacheControlDirective('private'));
616 $response->setCache(array('private' => true));
617 $this->assertFalse($response->headers->hasCacheControlDirective('public'));
618 $this->assertTrue($response->headers->hasCacheControlDirective('private'));
620 $response->setCache(array('private' => false));
621 $this->assertTrue($response->headers->hasCacheControlDirective('public'));
622 $this->assertFalse($response->headers->hasCacheControlDirective('private'));
624 $response->setCache(array('immutable' => true));
625 $this->assertTrue($response->headers->hasCacheControlDirective('immutable'));
627 $response->setCache(array('immutable' => false));
628 $this->assertFalse($response->headers->hasCacheControlDirective('immutable'));
631 public function testSendContent()
633 $response = new Response('test response rendering', 200);
636 $response->sendContent();
637 $string = ob_get_clean();
638 $this->assertContains('test response rendering', $string);
641 public function testSetPublic()
643 $response = new Response();
644 $response->setPublic();
646 $this->assertTrue($response->headers->hasCacheControlDirective('public'));
647 $this->assertFalse($response->headers->hasCacheControlDirective('private'));
650 public function testSetImmutable()
652 $response = new Response();
653 $response->setImmutable();
655 $this->assertTrue($response->headers->hasCacheControlDirective('immutable'));
658 public function testIsImmutable()
660 $response = new Response();
661 $response->setImmutable();
663 $this->assertTrue($response->isImmutable());
666 public function testSetExpires()
668 $response = new Response();
669 $response->setExpires(null);
671 $this->assertNull($response->getExpires(), '->setExpires() remove the header when passed null');
673 $now = $this->createDateTimeNow();
674 $response->setExpires($now);
676 $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp());
679 public function testSetLastModified()
681 $response = new Response();
682 $response->setLastModified($this->createDateTimeNow());
683 $this->assertNotNull($response->getLastModified());
685 $response->setLastModified(null);
686 $this->assertNull($response->getLastModified());
689 public function testIsInvalid()
691 $response = new Response();
694 $response->setStatusCode(99);
696 } catch (\InvalidArgumentException $e) {
697 $this->assertTrue($response->isInvalid());
701 $response->setStatusCode(650);
703 } catch (\InvalidArgumentException $e) {
704 $this->assertTrue($response->isInvalid());
707 $response = new Response('', 200);
708 $this->assertFalse($response->isInvalid());
712 * @dataProvider getStatusCodeFixtures
714 public function testSetStatusCode($code, $text, $expectedText)
716 $response = new Response();
718 $response->setStatusCode($code, $text);
720 $statusText = new \ReflectionProperty($response, 'statusText');
721 $statusText->setAccessible(true);
723 $this->assertEquals($expectedText, $statusText->getValue($response));
726 public function getStatusCodeFixtures()
729 array('200', null, 'OK'),
730 array('200', false, ''),
731 array('200', 'foo', 'foo'),
732 array('199', null, 'unknown status'),
733 array('199', false, ''),
734 array('199', 'foo', 'foo'),
738 public function testIsInformational()
740 $response = new Response('', 100);
741 $this->assertTrue($response->isInformational());
743 $response = new Response('', 200);
744 $this->assertFalse($response->isInformational());
747 public function testIsRedirectRedirection()
749 foreach (array(301, 302, 303, 307) as $code) {
750 $response = new Response('', $code);
751 $this->assertTrue($response->isRedirection());
752 $this->assertTrue($response->isRedirect());
755 $response = new Response('', 304);
756 $this->assertTrue($response->isRedirection());
757 $this->assertFalse($response->isRedirect());
759 $response = new Response('', 200);
760 $this->assertFalse($response->isRedirection());
761 $this->assertFalse($response->isRedirect());
763 $response = new Response('', 404);
764 $this->assertFalse($response->isRedirection());
765 $this->assertFalse($response->isRedirect());
767 $response = new Response('', 301, array('Location' => '/good-uri'));
768 $this->assertFalse($response->isRedirect('/bad-uri'));
769 $this->assertTrue($response->isRedirect('/good-uri'));
772 public function testIsNotFound()
774 $response = new Response('', 404);
775 $this->assertTrue($response->isNotFound());
777 $response = new Response('', 200);
778 $this->assertFalse($response->isNotFound());
781 public function testIsEmpty()
783 foreach (array(204, 304) as $code) {
784 $response = new Response('', $code);
785 $this->assertTrue($response->isEmpty());
788 $response = new Response('', 200);
789 $this->assertFalse($response->isEmpty());
792 public function testIsForbidden()
794 $response = new Response('', 403);
795 $this->assertTrue($response->isForbidden());
797 $response = new Response('', 200);
798 $this->assertFalse($response->isForbidden());
801 public function testIsOk()
803 $response = new Response('', 200);
804 $this->assertTrue($response->isOk());
806 $response = new Response('', 404);
807 $this->assertFalse($response->isOk());
810 public function testIsServerOrClientError()
812 $response = new Response('', 404);
813 $this->assertTrue($response->isClientError());
814 $this->assertFalse($response->isServerError());
816 $response = new Response('', 500);
817 $this->assertFalse($response->isClientError());
818 $this->assertTrue($response->isServerError());
821 public function testHasVary()
823 $response = new Response();
824 $this->assertFalse($response->hasVary());
826 $response->setVary('User-Agent');
827 $this->assertTrue($response->hasVary());
830 public function testSetEtag()
832 $response = new Response('', 200, array('ETag' => '"12345"'));
833 $response->setEtag();
835 $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null');
839 * @dataProvider validContentProvider
841 public function testSetContent($content)
843 $response = new Response();
844 $response->setContent($content);
845 $this->assertEquals((string) $content, $response->getContent());
849 * @expectedException \UnexpectedValueException
850 * @dataProvider invalidContentProvider
852 public function testSetContentInvalid($content)
854 $response = new Response();
855 $response->setContent($content);
858 public function testSettersAreChainable()
860 $response = new Response();
863 'setProtocolVersion' => '1.0',
864 'setCharset' => 'UTF-8',
866 'setPrivate' => null,
867 'setDate' => $this->createDateTimeNow(),
870 'setSharedMaxAge' => 1,
875 foreach ($setters as $setter => $arg) {
876 $this->assertEquals($response, $response->{$setter}($arg));
880 public function testNoDeprecationsAreTriggered()
882 new DefaultResponse();
883 $this->getMockBuilder(Response::class)->getMock();
885 // we just need to ensure that subclasses of Response can be created without any deprecations
886 // being triggered if the subclass does not override any final methods
887 $this->addToAssertionCount(1);
890 public function validContentProvider()
893 'obj' => array(new StringableObject()),
894 'string' => array('Foo'),
899 public function invalidContentProvider()
902 'obj' => array(new \stdClass()),
903 'array' => array(array()),
904 'bool' => array(true, '1'),
908 protected function createDateTimeOneHourAgo()
910 return $this->createDateTimeNow()->sub(new \DateInterval('PT1H'));
913 protected function createDateTimeOneHourLater()
915 return $this->createDateTimeNow()->add(new \DateInterval('PT1H'));
918 protected function createDateTimeNow()
920 $date = new \DateTime();
922 return $date->setTimestamp(time());
925 protected function provideResponse()
927 return new Response();
931 * @see http://github.com/zendframework/zend-diactoros for the canonical source repository
933 * @author Fábio Pacheco
934 * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
935 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
937 public function ianaCodesReasonPhrasesProvider()
939 if (!\in_array('https', stream_get_wrappers(), true)) {
940 $this->markTestSkipped('The "https" wrapper is not available');
943 $ianaHttpStatusCodes = new \DOMDocument();
945 libxml_set_streams_context(stream_context_create(array(
952 $ianaHttpStatusCodes->load('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml');
953 if (!$ianaHttpStatusCodes->relaxNGValidate(__DIR__.'/schema/http-status-codes.rng')) {
954 self::fail('Invalid IANA\'s HTTP status code list.');
957 $ianaCodesReasonPhrases = array();
959 $xpath = new \DOMXPath($ianaHttpStatusCodes);
960 $xpath->registerNamespace('ns', 'http://www.iana.org/assignments');
962 $records = $xpath->query('//ns:record');
963 foreach ($records as $record) {
964 $value = $xpath->query('.//ns:value', $record)->item(0)->nodeValue;
965 $description = $xpath->query('.//ns:description', $record)->item(0)->nodeValue;
967 if (\in_array($description, array('Unassigned', '(Unused)'), true)) {
971 if (preg_match('/^([0-9]+)\s*\-\s*([0-9]+)$/', $value, $matches)) {
972 for ($value = $matches[1]; $value <= $matches[2]; ++$value) {
973 $ianaCodesReasonPhrases[] = array($value, $description);
976 $ianaCodesReasonPhrases[] = array($value, $description);
980 return $ianaCodesReasonPhrases;
984 * @dataProvider ianaCodesReasonPhrasesProvider
986 public function testReasonPhraseDefaultsAgainstIana($code, $reasonPhrase)
988 $this->assertEquals($reasonPhrase, Response::$statusTexts[$code]);
992 class StringableObject
994 public function __toString()
1000 class DefaultResponse extends Response
1004 class ExtendedResponse extends Response
1006 public function setLastModified(\DateTime $date = null)
1010 public function getDate()