ResponseTest.php 15 KB

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