ResponseTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. $result = $response->body('json_decode');
  99. $this->assertEquals($data['property'], $result->property);
  100. $this->assertEquals($encoded, $response->body());
  101. $this->assertEquals($encoded, $response->body);
  102. $this->assertTrue(isset($response->body));
  103. }
  104. /**
  105. * Test accessor for json
  106. *
  107. * @return void
  108. */
  109. public function testBodyJson()
  110. {
  111. $data = [
  112. 'property' => 'value'
  113. ];
  114. $encoded = json_encode($data);
  115. $response = new Response([], $encoded);
  116. $this->assertTrue(isset($response->json));
  117. $this->assertEquals($data['property'], $response->json['property']);
  118. $data = '';
  119. $response = new Response([], $data);
  120. $this->assertNull($response->json);
  121. $data = json_encode([]);
  122. $response = new Response([], $data);
  123. $this->assertTrue(is_array($response->json));
  124. $data = json_encode(null);
  125. $response = new Response([], $data);
  126. $this->assertNull($response->json);
  127. $data = json_encode(false);
  128. $response = new Response([], $data);
  129. $this->assertFalse($response->json);
  130. $data = json_encode('');
  131. $response = new Response([], $data);
  132. $this->assertSame('', $response->json);
  133. }
  134. /**
  135. * Test accessor for json when set with PSR7 methods.
  136. *
  137. * @return void
  138. */
  139. public function testBodyJsonPsr7()
  140. {
  141. $data = [
  142. 'property' => 'value'
  143. ];
  144. $encoded = json_encode($data);
  145. $response = new Response([], '');
  146. $response->getBody()->write($encoded);
  147. $this->assertEquals($data, $response->json);
  148. }
  149. /**
  150. * Test accessor for xml
  151. *
  152. * @return void
  153. */
  154. public function testBodyXml()
  155. {
  156. $data = <<<XML
  157. <?xml version="1.0" encoding="utf-8"?>
  158. <root>
  159. <test>Test</test>
  160. </root>
  161. XML;
  162. $response = new Response([], $data);
  163. $this->assertTrue(isset($response->xml));
  164. $this->assertEquals('Test', (string)$response->xml->test);
  165. $data = '';
  166. $response = new Response([], $data);
  167. $this->assertFalse(isset($response->xml));
  168. }
  169. /**
  170. * Test isOk()
  171. *
  172. * @return void
  173. */
  174. public function testIsOk()
  175. {
  176. $headers = [
  177. 'HTTP/1.1 200 OK',
  178. 'Content-Type: text/html'
  179. ];
  180. $response = new Response($headers, 'ok');
  181. $this->assertTrue($response->isOk());
  182. $headers = [
  183. 'HTTP/1.1 201 Created',
  184. 'Content-Type: text/html'
  185. ];
  186. $response = new Response($headers, 'ok');
  187. $this->assertTrue($response->isOk());
  188. $headers = [
  189. 'HTTP/1.1 202 Accepted',
  190. 'Content-Type: text/html'
  191. ];
  192. $response = new Response($headers, 'ok');
  193. $this->assertTrue($response->isOk());
  194. $headers = [
  195. 'HTTP/1.1 301 Moved Permanently',
  196. 'Content-Type: text/html'
  197. ];
  198. $response = new Response($headers, '');
  199. $this->assertFalse($response->isOk());
  200. $headers = [
  201. 'HTTP/1.0 404 Not Found',
  202. 'Content-Type: text/html'
  203. ];
  204. $response = new Response($headers, '');
  205. $this->assertFalse($response->isOk());
  206. }
  207. /**
  208. * Test isRedirect()
  209. *
  210. * @return void
  211. */
  212. public function testIsRedirect()
  213. {
  214. $headers = [
  215. 'HTTP/1.1 200 OK',
  216. 'Content-Type: text/html'
  217. ];
  218. $response = new Response($headers, 'ok');
  219. $this->assertFalse($response->isRedirect());
  220. $headers = [
  221. 'HTTP/1.1 301 Moved Permanently',
  222. 'Location: /',
  223. 'Content-Type: text/html'
  224. ];
  225. $response = new Response($headers, '');
  226. $this->assertTrue($response->isRedirect());
  227. $headers = [
  228. 'HTTP/1.0 404 Not Found',
  229. 'Content-Type: text/html'
  230. ];
  231. $response = new Response($headers, '');
  232. $this->assertFalse($response->isRedirect());
  233. }
  234. /**
  235. * Test parsing / getting cookies.
  236. *
  237. * @return void
  238. */
  239. public function testCookie()
  240. {
  241. $headers = [
  242. 'HTTP/1.0 200 Ok',
  243. 'Set-Cookie: test=value',
  244. 'Set-Cookie: session=123abc',
  245. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  246. ];
  247. $response = new Response($headers, '');
  248. $this->assertEquals('value', $response->cookie('test'));
  249. $this->assertEquals('123abc', $response->cookie('session'));
  250. $this->assertEquals('soon', $response->cookie('expiring'));
  251. $result = $response->cookie('expiring', true);
  252. $this->assertTrue($result['httponly']);
  253. $this->assertTrue($result['secure']);
  254. $this->assertEquals(
  255. 'Wed, 09-Jun-2021 10:18:14 GMT',
  256. $result['expires']
  257. );
  258. $this->assertEquals('/', $result['path']);
  259. $result = $response->header('set-cookie');
  260. $this->assertCount(3, $result, 'Should be an array.');
  261. $this->assertTrue(isset($response->cookies));
  262. $this->assertEquals(
  263. 'soon',
  264. $response->cookies['expiring']['value']
  265. );
  266. }
  267. /**
  268. * Test accessing cookies through the PSR7-like methods
  269. *
  270. * @return void
  271. */
  272. public function testGetCookies()
  273. {
  274. $headers = [
  275. 'HTTP/1.0 200 Ok',
  276. 'Set-Cookie: test=value',
  277. 'Set-Cookie: session=123abc',
  278. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  279. ];
  280. $response = new Response($headers, '');
  281. $this->assertNull($response->getCookie('undef'));
  282. $this->assertEquals('value', $response->getCookie('test'));
  283. $this->assertEquals('soon', $response->getCookie('expiring'));
  284. $result = $response->getCookieData('expiring');
  285. $this->assertEquals('soon', $result['value']);
  286. $this->assertTrue($result['httponly']);
  287. $this->assertTrue($result['secure']);
  288. $this->assertEquals(
  289. 'Wed, 09-Jun-2021 10:18:14 GMT',
  290. $result['expires']
  291. );
  292. $this->assertEquals('/', $result['path']);
  293. $result = $response->getCookies();
  294. $this->assertCount(3, $result);
  295. $this->assertArrayHasKey('test', $result);
  296. $this->assertArrayHasKey('session', $result);
  297. $this->assertArrayHasKey('expiring', $result);
  298. }
  299. /**
  300. * Test accessing cookie collection
  301. *
  302. * @return void
  303. */
  304. public function testGetCookieCollection()
  305. {
  306. $headers = [
  307. 'HTTP/1.0 200 Ok',
  308. 'Set-Cookie: test=value',
  309. 'Set-Cookie: session=123abc',
  310. 'Set-Cookie: expiring=soon; Expires=Wed, 09-Jun-2021 10:18:14 GMT; Path=/; HttpOnly; Secure;',
  311. ];
  312. $response = new Response($headers, '');
  313. $cookies = $response->getCookieCollection();
  314. $this->assertInstanceOf(CookieCollection::class, $cookies);
  315. $this->assertTrue($cookies->has('test'));
  316. $this->assertTrue($cookies->has('session'));
  317. $this->assertTrue($cookies->has('expiring'));
  318. $this->assertSame('123abc', $cookies->get('session')->getValue());
  319. }
  320. /**
  321. * Test statusCode()
  322. *
  323. * @return void
  324. */
  325. public function testStatusCode()
  326. {
  327. $headers = [
  328. 'HTTP/1.0 404 Not Found',
  329. 'Content-Type: text/html'
  330. ];
  331. $response = new Response($headers, '');
  332. $this->assertSame(404, $response->statusCode());
  333. $this->assertSame(404, $response->getStatusCode());
  334. $this->assertSame(404, $response->code);
  335. $this->assertTrue(isset($response->code));
  336. }
  337. /**
  338. * Test reading the encoding out.
  339. *
  340. * @return void
  341. */
  342. public function testEncoding()
  343. {
  344. $headers = [
  345. 'HTTP/1.0 200 Ok',
  346. ];
  347. $response = new Response($headers, '');
  348. $this->assertNull($response->encoding());
  349. $headers = [
  350. 'HTTP/1.0 200 Ok',
  351. 'Content-Type: text/html'
  352. ];
  353. $response = new Response($headers, '');
  354. $this->assertNull($response->getEncoding());
  355. $this->assertNull($response->encoding());
  356. $headers = [
  357. 'HTTP/1.0 200 Ok',
  358. 'Content-Type: text/html; charset="UTF-8"'
  359. ];
  360. $response = new Response($headers, '');
  361. $this->assertEquals('UTF-8', $response->getEncoding());
  362. $this->assertEquals('UTF-8', $response->encoding());
  363. $headers = [
  364. 'HTTP/1.0 200 Ok',
  365. "Content-Type: text/html; charset='ISO-8859-1'"
  366. ];
  367. $response = new Response($headers, '');
  368. $this->assertEquals('ISO-8859-1', $response->getEncoding());
  369. $this->assertEquals('ISO-8859-1', $response->encoding());
  370. }
  371. /**
  372. * Test that gzip responses are automatically decompressed.
  373. *
  374. * @return void
  375. */
  376. public function testAutoDecodeGzipBody()
  377. {
  378. $headers = [
  379. 'HTTP/1.0 200 OK',
  380. 'Content-Encoding: gzip',
  381. 'Content-Length: 32',
  382. 'Content-Type: text/html; charset=UTF-8'
  383. ];
  384. $body = base64_decode('H4sIAAAAAAAAA/NIzcnJVyjPL8pJUQQAlRmFGwwAAAA=');
  385. $response = new Response($headers, $body);
  386. $this->assertEquals('Hello world!', $response->body);
  387. }
  388. }