ResponseTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  10. * @link https://cakephp.org CakePHP(tm) Project
  11. * @since 3.0.0
  12. * @license https://opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Test\TestCase\Http\Client;
  15. use Cake\Chronos\Chronos;
  16. use Cake\Http\Client\Response;
  17. use Cake\Http\Cookie\Cookie;
  18. use Cake\Http\Cookie\CookieCollection;
  19. use Cake\TestSuite\TestCase;
  20. /**
  21. * HTTP response test.
  22. */
  23. class ResponseTest extends TestCase
  24. {
  25. /**
  26. * Test parsing headers and reading with PSR7 methods.
  27. *
  28. * @return void
  29. */
  30. public function testHeaderParsingPsr7()
  31. {
  32. $headers = [
  33. 'HTTP/1.0 200 OK',
  34. 'Content-Type : text/html;charset="UTF-8"',
  35. 'date: Tue, 25 Dec 2012 04:43:47 GMT',
  36. ];
  37. $response = new Response($headers, 'winner!');
  38. $this->assertEquals('1.0', $response->getProtocolVersion());
  39. $this->assertSame(200, $response->getStatusCode());
  40. $this->assertEquals('OK', $response->getReasonPhrase());
  41. $this->assertEquals(
  42. 'text/html;charset="UTF-8"',
  43. $response->getHeaderLine('content-type')
  44. );
  45. $this->assertEquals(
  46. 'Tue, 25 Dec 2012 04:43:47 GMT',
  47. $response->getHeaderLine('Date')
  48. );
  49. $this->assertEquals('winner!', '' . $response->getBody());
  50. }
  51. /**
  52. * Test parsing headers and capturing content
  53. *
  54. * @return void
  55. */
  56. public function testHeaderParsing()
  57. {
  58. $headers = [
  59. 'HTTP/1.0 200 OK',
  60. 'Content-Type : text/html;charset="UTF-8"',
  61. 'date: Tue, 25 Dec 2012 04:43:47 GMT',
  62. ];
  63. $response = new Response($headers, 'ok');
  64. $this->assertSame(200, $response->statusCode());
  65. $this->assertEquals('1.0', $response->version());
  66. $this->assertEquals(
  67. 'text/html;charset="UTF-8"',
  68. $response->header('content-type')
  69. );
  70. $this->assertEquals(
  71. 'Tue, 25 Dec 2012 04:43:47 GMT',
  72. $response->header('Date')
  73. );
  74. $this->assertEquals(
  75. 'text/html;charset="UTF-8"',
  76. $response->headers['Content-Type']
  77. );
  78. $this->assertTrue(isset($response->headers));
  79. $headers = [
  80. 'HTTP/1.0 200',
  81. ];
  82. $response = new Response($headers, 'ok');
  83. $this->assertEquals('1.0', $response->version());
  84. $this->assertSame(200, $response->statusCode());
  85. }
  86. /**
  87. * Test body()
  88. *
  89. * @return void
  90. */
  91. public function testBody()
  92. {
  93. $data = [
  94. 'property' => 'value'
  95. ];
  96. $encoded = json_encode($data);
  97. $response = new Response([], $encoded);
  98. $this->assertEquals($encoded, $response->getBody()->getContents());
  99. $this->assertEquals($encoded, $response->body());
  100. $result = $response->body('json_decode');
  101. $this->assertEquals($data['property'], $result->property);
  102. $this->assertEquals($encoded, $response->body);
  103. $this->assertTrue(isset($response->body));
  104. }
  105. /**
  106. * Test accessor for json
  107. *
  108. * @return void
  109. */
  110. public function testBodyJson()
  111. {
  112. $data = [
  113. 'property' => 'value'
  114. ];
  115. $encoded = json_encode($data);
  116. $response = new Response([], $encoded);
  117. $this->assertTrue(isset($response->json));
  118. $this->assertEquals($data['property'], $response->json['property']);
  119. $data = '';
  120. $response = new Response([], $data);
  121. $this->assertNull($response->json);
  122. $data = json_encode([]);
  123. $response = new Response([], $data);
  124. $this->assertTrue(is_array($response->json));
  125. $data = json_encode(null);
  126. $response = new Response([], $data);
  127. $this->assertNull($response->json);
  128. $data = json_encode(false);
  129. $response = new Response([], $data);
  130. $this->assertFalse($response->json);
  131. $data = json_encode('');
  132. $response = new Response([], $data);
  133. $this->assertSame('', $response->json);
  134. }
  135. /**
  136. * Test accessor for json when set with PSR7 methods.
  137. *
  138. * @return void
  139. */
  140. public function testBodyJsonPsr7()
  141. {
  142. $data = [
  143. 'property' => 'value'
  144. ];
  145. $encoded = json_encode($data);
  146. $response = new Response([], '');
  147. $response->getBody()->write($encoded);
  148. $this->assertEquals($data, $response->json);
  149. }
  150. /**
  151. * Test accessor for xml
  152. *
  153. * @return void
  154. */
  155. public function testBodyXml()
  156. {
  157. $data = <<<XML
  158. <?xml version="1.0" encoding="utf-8"?>
  159. <root>
  160. <test>Test</test>
  161. </root>
  162. XML;
  163. $response = new Response([], $data);
  164. $this->assertTrue(isset($response->xml));
  165. $this->assertEquals('Test', (string)$response->xml->test);
  166. $data = '';
  167. $response = new Response([], $data);
  168. $this->assertFalse(isset($response->xml));
  169. }
  170. /**
  171. * Test isOk()
  172. *
  173. * @return void
  174. */
  175. public function testIsOk()
  176. {
  177. $headers = [
  178. 'HTTP/1.1 200 OK',
  179. 'Content-Type: text/html'
  180. ];
  181. $response = new Response($headers, 'ok');
  182. $this->assertTrue($response->isOk());
  183. $headers = [
  184. 'HTTP/1.1 201 Created',
  185. 'Content-Type: text/html'
  186. ];
  187. $response = new Response($headers, 'ok');
  188. $this->assertTrue($response->isOk());
  189. $headers = [
  190. 'HTTP/1.1 202 Accepted',
  191. 'Content-Type: text/html'
  192. ];
  193. $response = new Response($headers, 'ok');
  194. $this->assertTrue($response->isOk());
  195. $headers = [
  196. 'HTTP/1.1 301 Moved Permanently',
  197. 'Content-Type: text/html'
  198. ];
  199. $response = new Response($headers, '');
  200. $this->assertFalse($response->isOk());
  201. $headers = [
  202. 'HTTP/1.0 404 Not Found',
  203. 'Content-Type: text/html'
  204. ];
  205. $response = new Response($headers, '');
  206. $this->assertFalse($response->isOk());
  207. }
  208. /**
  209. * Test isRedirect()
  210. *
  211. * @return void
  212. */
  213. public function testIsRedirect()
  214. {
  215. $headers = [
  216. 'HTTP/1.1 200 OK',
  217. 'Content-Type: text/html'
  218. ];
  219. $response = new Response($headers, 'ok');
  220. $this->assertFalse($response->isRedirect());
  221. $headers = [
  222. 'HTTP/1.1 301 Moved Permanently',
  223. 'Location: /',
  224. 'Content-Type: text/html'
  225. ];
  226. $response = new Response($headers, '');
  227. $this->assertTrue($response->isRedirect());
  228. $headers = [
  229. 'HTTP/1.0 404 Not Found',
  230. 'Content-Type: text/html'
  231. ];
  232. $response = new Response($headers, '');
  233. $this->assertFalse($response->isRedirect());
  234. }
  235. /**
  236. * Test parsing / getting cookies.
  237. *
  238. * @return void
  239. */
  240. public function testCookie()
  241. {
  242. $headers = [
  243. 'HTTP/1.0 200 Ok',
  244. 'Set-Cookie: test=value',
  245. 'Set-Cookie: session=123abc',
  246. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  247. ];
  248. $response = new Response($headers, '');
  249. $this->assertEquals('value', $response->cookie('test'));
  250. $this->assertEquals('123abc', $response->cookie('session'));
  251. $this->assertEquals('soon', $response->cookie('expiring'));
  252. $result = $response->cookie('expiring', true);
  253. $this->assertTrue($result['httponly']);
  254. $this->assertTrue($result['secure']);
  255. $this->assertEquals(
  256. 'Wed, 09-Jun-2021 10:18:14 GMT',
  257. $result['expires']
  258. );
  259. $this->assertEquals('/', $result['path']);
  260. $result = $response->header('set-cookie');
  261. $this->assertCount(3, $result, 'Should be an array.');
  262. $this->assertTrue(isset($response->cookies));
  263. $this->assertEquals(
  264. 'soon',
  265. $response->cookies['expiring']['value']
  266. );
  267. }
  268. /**
  269. * Test accessing cookies through the PSR7-like methods
  270. *
  271. * @return void
  272. */
  273. public function testGetCookies()
  274. {
  275. $headers = [
  276. 'HTTP/1.0 200 Ok',
  277. 'Set-Cookie: test=value',
  278. 'Set-Cookie: session=123abc',
  279. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  280. ];
  281. $response = new Response($headers, '');
  282. $this->assertNull($response->getCookie('undef'));
  283. $this->assertEquals('value', $response->getCookie('test'));
  284. $this->assertEquals('soon', $response->getCookie('expiring'));
  285. $result = $response->getCookieData('expiring');
  286. $this->assertEquals('soon', $result['value']);
  287. $this->assertTrue($result['httponly']);
  288. $this->assertTrue($result['secure']);
  289. $this->assertEquals(
  290. 'Wed, 09-Jun-2021 10:18:14 GMT',
  291. $result['expires']
  292. );
  293. $this->assertEquals('/', $result['path']);
  294. $result = $response->getCookies();
  295. $this->assertCount(3, $result);
  296. $this->assertArrayHasKey('test', $result);
  297. $this->assertArrayHasKey('session', $result);
  298. $this->assertArrayHasKey('expiring', $result);
  299. }
  300. /**
  301. * Test accessing cookie collection
  302. *
  303. * @return void
  304. */
  305. public function testGetCookieCollection()
  306. {
  307. $headers = [
  308. 'HTTP/1.0 200 Ok',
  309. 'Set-Cookie: test=value',
  310. 'Set-Cookie: session=123abc',
  311. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  312. ];
  313. $response = new Response($headers, '');
  314. $cookies = $response->getCookieCollection();
  315. $this->assertInstanceOf(CookieCollection::class, $cookies);
  316. $this->assertTrue($cookies->has('test'));
  317. $this->assertTrue($cookies->has('session'));
  318. $this->assertTrue($cookies->has('expiring'));
  319. $this->assertSame('123abc', $cookies->get('session')->getValue());
  320. }
  321. /**
  322. * Test statusCode()
  323. *
  324. * @return void
  325. */
  326. public function testStatusCode()
  327. {
  328. $headers = [
  329. 'HTTP/1.0 404 Not Found',
  330. 'Content-Type: text/html'
  331. ];
  332. $response = new Response($headers, '');
  333. $this->assertSame(404, $response->statusCode());
  334. $this->assertSame(404, $response->getStatusCode());
  335. $this->assertSame(404, $response->code);
  336. $this->assertTrue(isset($response->code));
  337. }
  338. /**
  339. * Test reading the encoding out.
  340. *
  341. * @return void
  342. */
  343. public function testEncoding()
  344. {
  345. $headers = [
  346. 'HTTP/1.0 200 Ok',
  347. ];
  348. $response = new Response($headers, '');
  349. $this->assertNull($response->encoding());
  350. $headers = [
  351. 'HTTP/1.0 200 Ok',
  352. 'Content-Type: text/html'
  353. ];
  354. $response = new Response($headers, '');
  355. $this->assertNull($response->getEncoding());
  356. $this->assertNull($response->encoding());
  357. $headers = [
  358. 'HTTP/1.0 200 Ok',
  359. 'Content-Type: text/html; charset="UTF-8"'
  360. ];
  361. $response = new Response($headers, '');
  362. $this->assertEquals('UTF-8', $response->getEncoding());
  363. $this->assertEquals('UTF-8', $response->encoding());
  364. $headers = [
  365. 'HTTP/1.0 200 Ok',
  366. "Content-Type: text/html; charset='ISO-8859-1'"
  367. ];
  368. $response = new Response($headers, '');
  369. $this->assertEquals('ISO-8859-1', $response->getEncoding());
  370. $this->assertEquals('ISO-8859-1', $response->encoding());
  371. }
  372. /**
  373. * Test that gzip responses are automatically decompressed.
  374. *
  375. * @return void
  376. */
  377. public function testAutoDecodeGzipBody()
  378. {
  379. $headers = [
  380. 'HTTP/1.0 200 OK',
  381. 'Content-Encoding: gzip',
  382. 'Content-Length: 32',
  383. 'Content-Type: text/html; charset=UTF-8'
  384. ];
  385. $body = base64_decode('H4sIAAAAAAAAA/NIzcnJVyjPL8pJUQQAlRmFGwwAAAA=');
  386. $response = new Response($headers, $body);
  387. $this->assertEquals('Hello world!', $response->body);
  388. }
  389. }