ClientTest.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  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;
  15. use Cake\Http\Client;
  16. use Cake\Http\Client\Request;
  17. use Cake\Http\Client\Response;
  18. use Cake\Http\Cookie\Cookie;
  19. use Cake\Http\Cookie\CookieCollection;
  20. use Cake\TestSuite\TestCase;
  21. use InvalidArgumentException;
  22. /**
  23. * HTTP client test.
  24. */
  25. class ClientTest extends TestCase
  26. {
  27. /**
  28. * Test storing config options and modifying them.
  29. *
  30. * @return void
  31. */
  32. public function testConstructConfig()
  33. {
  34. $config = [
  35. 'scheme' => 'http',
  36. 'host' => 'example.org',
  37. ];
  38. $http = new Client($config);
  39. $result = $http->getConfig();
  40. foreach ($config as $key => $val) {
  41. $this->assertEquals($val, $result[$key]);
  42. }
  43. $result = $http->setConfig([
  44. 'auth' => ['username' => 'mark', 'password' => 'secret']
  45. ]);
  46. $this->assertSame($result, $http);
  47. $result = $http->getConfig();
  48. $expected = [
  49. 'scheme' => 'http',
  50. 'host' => 'example.org',
  51. 'auth' => ['username' => 'mark', 'password' => 'secret']
  52. ];
  53. foreach ($expected as $key => $val) {
  54. $this->assertEquals($val, $result[$key]);
  55. }
  56. }
  57. /**
  58. * testAdapterInstanceCheck
  59. *
  60. * @return void
  61. */
  62. public function testAdapterInstanceCheck()
  63. {
  64. $this->expectException(InvalidArgumentException::class);
  65. $this->expectExceptionMessage('Adapter must be an instance of Cake\Http\Client\AdapterInterface');
  66. new Client(['adapter' => 'stdClass']);
  67. }
  68. /**
  69. * Data provider for buildUrl() tests
  70. *
  71. * @return array
  72. */
  73. public static function urlProvider()
  74. {
  75. return [
  76. [
  77. 'http://example.com/test.html',
  78. 'http://example.com/test.html',
  79. [],
  80. null,
  81. 'Null options'
  82. ],
  83. [
  84. 'http://example.com/test.html',
  85. 'http://example.com/test.html',
  86. [],
  87. [],
  88. 'Simple string'
  89. ],
  90. [
  91. 'http://example.com/test.html',
  92. '/test.html',
  93. [],
  94. ['host' => 'example.com'],
  95. 'host name option',
  96. ],
  97. [
  98. 'https://example.com/test.html',
  99. '/test.html',
  100. [],
  101. ['host' => 'example.com', 'scheme' => 'https'],
  102. 'HTTPS',
  103. ],
  104. [
  105. 'http://example.com:8080/test.html',
  106. '/test.html',
  107. [],
  108. ['host' => 'example.com', 'port' => '8080'],
  109. 'Non standard port',
  110. ],
  111. [
  112. 'http://example.com/test.html',
  113. '/test.html',
  114. [],
  115. ['host' => 'example.com', 'port' => '80'],
  116. 'standard port, does not display'
  117. ],
  118. [
  119. 'https://example.com/test.html',
  120. '/test.html',
  121. [],
  122. ['host' => 'example.com', 'scheme' => 'https', 'port' => '443'],
  123. 'standard port, does not display'
  124. ],
  125. [
  126. 'http://example.com/test.html',
  127. 'http://example.com/test.html',
  128. [],
  129. ['host' => 'example.com', 'scheme' => 'https'],
  130. 'options do not duplicate'
  131. ],
  132. [
  133. 'http://example.com/search?q=hi+there&cat%5Bid%5D%5B0%5D=2&cat%5Bid%5D%5B1%5D=3',
  134. 'http://example.com/search',
  135. ['q' => 'hi there', 'cat' => ['id' => [2, 3]]],
  136. [],
  137. 'query string data.'
  138. ],
  139. [
  140. 'http://example.com/search?q=hi+there&id=12',
  141. 'http://example.com/search?q=hi+there',
  142. ['id' => '12'],
  143. [],
  144. 'query string data with some already on the url.'
  145. ],
  146. [
  147. 'http://example.com/test.html',
  148. '//test.html',
  149. [],
  150. [
  151. 'scheme' => 'http',
  152. 'host' => 'example.com',
  153. 'protocolRelative' => false
  154. ],
  155. 'url with a double slash',
  156. ],
  157. [
  158. 'http://example.com/test.html',
  159. '//example.com/test.html',
  160. [],
  161. [
  162. 'scheme' => 'http',
  163. 'protocolRelative' => true
  164. ],
  165. 'protocol relative url',
  166. ],
  167. ];
  168. }
  169. /**
  170. * @dataProvider urlProvider
  171. */
  172. public function testBuildUrl($expected, $url, $query, $opts)
  173. {
  174. $http = new Client();
  175. $result = $http->buildUrl($url, $query, $opts);
  176. $this->assertEquals($expected, $result);
  177. }
  178. /**
  179. * test simple get request with headers & cookies.
  180. *
  181. * @return void
  182. */
  183. public function testGetSimpleWithHeadersAndCookies()
  184. {
  185. $response = new Response();
  186. $headers = [
  187. 'User-Agent' => 'Cake',
  188. 'Connection' => 'close',
  189. 'Content-Type' => 'application/x-www-form-urlencoded',
  190. ];
  191. $cookies = [
  192. 'split' => 'value'
  193. ];
  194. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  195. ->setMethods(['send'])
  196. ->getMock();
  197. $mock->expects($this->once())
  198. ->method('send')
  199. ->with($this->callback(function ($request) use ($cookies, $headers) {
  200. $this->assertInstanceOf('Cake\Http\Client\Request', $request);
  201. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  202. $this->assertEquals('http://cakephp.org/test.html', $request->getUri() . '');
  203. $this->assertEquals('split=value', $request->getHeaderLine('Cookie'));
  204. $this->assertEquals($headers['Content-Type'], $request->getHeaderLine('content-type'));
  205. $this->assertEquals($headers['Connection'], $request->getHeaderLine('connection'));
  206. return true;
  207. }))
  208. ->will($this->returnValue([$response]));
  209. $http = new Client(['adapter' => $mock]);
  210. $result = $http->get('http://cakephp.org/test.html', [], [
  211. 'headers' => $headers,
  212. 'cookies' => $cookies,
  213. ]);
  214. $this->assertSame($result, $response);
  215. }
  216. /**
  217. * test get request with no data
  218. *
  219. * @return void
  220. */
  221. public function testGetNoData()
  222. {
  223. $response = new Response();
  224. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  225. ->setMethods(['send'])
  226. ->getMock();
  227. $mock->expects($this->once())
  228. ->method('send')
  229. ->with($this->callback(function ($request) {
  230. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  231. $this->assertEmpty($request->getHeaderLine('Content-Type'), 'Should have no content-type set');
  232. $this->assertEquals(
  233. 'http://cakephp.org/search',
  234. $request->getUri() . ''
  235. );
  236. return true;
  237. }))
  238. ->will($this->returnValue([$response]));
  239. $http = new Client([
  240. 'host' => 'cakephp.org',
  241. 'adapter' => $mock
  242. ]);
  243. $result = $http->get('/search');
  244. $this->assertSame($result, $response);
  245. }
  246. /**
  247. * test get request with querystring data
  248. *
  249. * @return void
  250. */
  251. public function testGetQuerystring()
  252. {
  253. $response = new Response();
  254. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  255. ->setMethods(['send'])
  256. ->getMock();
  257. $mock->expects($this->once())
  258. ->method('send')
  259. ->with($this->callback(function ($request) {
  260. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  261. $this->assertEquals(
  262. 'http://cakephp.org/search?q=hi+there&Category%5Bid%5D%5B0%5D=2&Category%5Bid%5D%5B1%5D=3',
  263. $request->getUri() . ''
  264. );
  265. return true;
  266. }))
  267. ->will($this->returnValue([$response]));
  268. $http = new Client([
  269. 'host' => 'cakephp.org',
  270. 'adapter' => $mock
  271. ]);
  272. $result = $http->get('/search', [
  273. 'q' => 'hi there',
  274. 'Category' => ['id' => [2, 3]]
  275. ]);
  276. $this->assertSame($result, $response);
  277. }
  278. /**
  279. * test get request with string of query data.
  280. *
  281. * @return void
  282. */
  283. public function testGetQuerystringString()
  284. {
  285. $response = new Response();
  286. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  287. ->setMethods(['send'])
  288. ->getMock();
  289. $mock->expects($this->once())
  290. ->method('send')
  291. ->with($this->callback(function ($request) {
  292. $this->assertEquals(
  293. 'http://cakephp.org/search?q=hi+there&Category%5Bid%5D%5B0%5D=2&Category%5Bid%5D%5B1%5D=3',
  294. $request->getUri() . ''
  295. );
  296. return true;
  297. }))
  298. ->will($this->returnValue([$response]));
  299. $http = new Client([
  300. 'host' => 'cakephp.org',
  301. 'adapter' => $mock
  302. ]);
  303. $data = [
  304. 'q' => 'hi there',
  305. 'Category' => ['id' => [2, 3]]
  306. ];
  307. $result = $http->get('/search', http_build_query($data));
  308. $this->assertSame($response, $result);
  309. }
  310. /**
  311. * Test a GET with a request body. Services like
  312. * elasticsearch use this feature.
  313. *
  314. * @return void
  315. */
  316. public function testGetWithContent()
  317. {
  318. $response = new Response();
  319. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  320. ->setMethods(['send'])
  321. ->getMock();
  322. $mock->expects($this->once())
  323. ->method('send')
  324. ->with($this->callback(function ($request) {
  325. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  326. $this->assertEquals('http://cakephp.org/search', '' . $request->getUri());
  327. $this->assertEquals('some data', '' . $request->getBody());
  328. return true;
  329. }))
  330. ->will($this->returnValue([$response]));
  331. $http = new Client([
  332. 'host' => 'cakephp.org',
  333. 'adapter' => $mock
  334. ]);
  335. $result = $http->get('/search', [
  336. '_content' => 'some data'
  337. ]);
  338. $this->assertSame($result, $response);
  339. }
  340. /**
  341. * Test invalid authentication types throw exceptions.
  342. *
  343. * @return void
  344. */
  345. public function testInvalidAuthenticationType()
  346. {
  347. $this->expectException(\Cake\Core\Exception\Exception::class);
  348. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  349. ->setMethods(['send'])
  350. ->getMock();
  351. $mock->expects($this->never())
  352. ->method('send');
  353. $http = new Client([
  354. 'host' => 'cakephp.org',
  355. 'adapter' => $mock
  356. ]);
  357. $result = $http->get('/', [], [
  358. 'auth' => ['type' => 'horribly broken']
  359. ]);
  360. }
  361. /**
  362. * Test setting basic authentication with get
  363. *
  364. * @return void
  365. */
  366. public function testGetWithAuthenticationAndProxy()
  367. {
  368. $response = new Response();
  369. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  370. ->setMethods(['send'])
  371. ->getMock();
  372. $headers = [
  373. 'Authorization' => 'Basic ' . base64_encode('mark:secret'),
  374. 'Proxy-Authorization' => 'Basic ' . base64_encode('mark:pass'),
  375. ];
  376. $mock->expects($this->once())
  377. ->method('send')
  378. ->with($this->callback(function ($request) use ($headers) {
  379. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  380. $this->assertEquals('http://cakephp.org/', '' . $request->getUri());
  381. $this->assertEquals($headers['Authorization'], $request->getHeaderLine('Authorization'));
  382. $this->assertEquals($headers['Proxy-Authorization'], $request->getHeaderLine('Proxy-Authorization'));
  383. return true;
  384. }))
  385. ->will($this->returnValue([$response]));
  386. $http = new Client([
  387. 'host' => 'cakephp.org',
  388. 'adapter' => $mock
  389. ]);
  390. $result = $http->get('/', [], [
  391. 'auth' => ['username' => 'mark', 'password' => 'secret'],
  392. 'proxy' => ['username' => 'mark', 'password' => 'pass'],
  393. ]);
  394. $this->assertSame($result, $response);
  395. }
  396. /**
  397. * Test authentication adapter that mutates request.
  398. *
  399. * @group deprecated
  400. * @return void
  401. */
  402. public function testAuthenticationWithMutation()
  403. {
  404. $this->deprecated(function () {
  405. static::setAppNamespace();
  406. $response = new Response();
  407. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  408. ->setMethods(['send'])
  409. ->getMock();
  410. $headers = [
  411. 'Authorization' => 'Bearer abc123',
  412. 'Proxy-Authorization' => 'Bearer abc123',
  413. ];
  414. $mock->expects($this->once())
  415. ->method('send')
  416. ->with($this->callback(function ($request) use ($headers) {
  417. $this->assertEquals(Request::METHOD_GET, $request->getMethod());
  418. $this->assertEquals('http://cakephp.org/', '' . $request->getUri());
  419. $this->assertEquals($headers['Authorization'], $request->getHeaderLine('Authorization'));
  420. $this->assertEquals($headers['Proxy-Authorization'], $request->getHeaderLine('Proxy-Authorization'));
  421. return true;
  422. }))
  423. ->will($this->returnValue([$response]));
  424. $http = new Client([
  425. 'host' => 'cakephp.org',
  426. 'adapter' => $mock
  427. ]);
  428. $result = $http->get('/', [], [
  429. 'auth' => ['type' => 'TestApp\Http\CompatAuth'],
  430. 'proxy' => ['type' => 'TestApp\Http\CompatAuth'],
  431. ]);
  432. $this->assertSame($result, $response);
  433. });
  434. }
  435. /**
  436. * Return a list of HTTP methods.
  437. *
  438. * @return array
  439. */
  440. public static function methodProvider()
  441. {
  442. return [
  443. [Request::METHOD_GET],
  444. [Request::METHOD_POST],
  445. [Request::METHOD_PUT],
  446. [Request::METHOD_DELETE],
  447. [Request::METHOD_PATCH],
  448. [Request::METHOD_OPTIONS],
  449. [Request::METHOD_TRACE],
  450. ];
  451. }
  452. /**
  453. * test simple POST request.
  454. *
  455. * @dataProvider methodProvider
  456. * @return void
  457. */
  458. public function testMethodsSimple($method)
  459. {
  460. $response = new Response();
  461. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  462. ->setMethods(['send'])
  463. ->getMock();
  464. $mock->expects($this->once())
  465. ->method('send')
  466. ->with($this->callback(function ($request) use ($method) {
  467. $this->assertInstanceOf('Cake\Http\Client\Request', $request);
  468. $this->assertEquals($method, $request->getMethod());
  469. $this->assertEquals('http://cakephp.org/projects/add', '' . $request->getUri());
  470. return true;
  471. }))
  472. ->will($this->returnValue([$response]));
  473. $http = new Client([
  474. 'host' => 'cakephp.org',
  475. 'adapter' => $mock
  476. ]);
  477. $result = $http->{$method}('/projects/add');
  478. $this->assertSame($result, $response);
  479. }
  480. /**
  481. * Provider for testing the type option.
  482. *
  483. * @return array
  484. */
  485. public static function typeProvider()
  486. {
  487. return [
  488. ['application/json', 'application/json'],
  489. ['json', 'application/json'],
  490. ['xml', 'application/xml'],
  491. ['application/xml', 'application/xml'],
  492. ];
  493. }
  494. /**
  495. * Test that using the 'type' option sets the correct headers
  496. *
  497. * @dataProvider typeProvider
  498. * @return void
  499. */
  500. public function testPostWithTypeKey($type, $mime)
  501. {
  502. $response = new Response();
  503. $data = 'some data';
  504. $headers = [
  505. 'Content-Type' => $mime,
  506. 'Accept' => $mime,
  507. ];
  508. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  509. ->setMethods(['send'])
  510. ->getMock();
  511. $mock->expects($this->once())
  512. ->method('send')
  513. ->with($this->callback(function ($request) use ($headers) {
  514. $this->assertEquals(Request::METHOD_POST, $request->getMethod());
  515. $this->assertEquals($headers['Content-Type'], $request->getHeaderLine('Content-Type'));
  516. $this->assertEquals($headers['Accept'], $request->getHeaderLine('Accept'));
  517. return true;
  518. }))
  519. ->will($this->returnValue([$response]));
  520. $http = new Client([
  521. 'host' => 'cakephp.org',
  522. 'adapter' => $mock
  523. ]);
  524. $http->post('/projects/add', $data, ['type' => $type]);
  525. }
  526. /**
  527. * Test that string payloads with no content type have a default content-type set.
  528. *
  529. * @return void
  530. */
  531. public function testPostWithStringDataDefaultsToFormEncoding()
  532. {
  533. $response = new Response();
  534. $data = 'some=value&more=data';
  535. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  536. ->setMethods(['send'])
  537. ->getMock();
  538. $mock->expects($this->any())
  539. ->method('send')
  540. ->with($this->callback(function ($request) use ($data) {
  541. $this->assertEquals($data, '' . $request->getBody());
  542. $this->assertEquals('application/x-www-form-urlencoded', $request->getHeaderLine('content-type'));
  543. return true;
  544. }))
  545. ->will($this->returnValue([$response]));
  546. $http = new Client([
  547. 'host' => 'cakephp.org',
  548. 'adapter' => $mock
  549. ]);
  550. $http->post('/projects/add', $data);
  551. $http->put('/projects/add', $data);
  552. $http->delete('/projects/add', $data);
  553. }
  554. /**
  555. * Test that exceptions are raised on invalid types.
  556. *
  557. * @return void
  558. */
  559. public function testExceptionOnUnknownType()
  560. {
  561. $this->expectException(\Cake\Core\Exception\Exception::class);
  562. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  563. ->setMethods(['send'])
  564. ->getMock();
  565. $mock->expects($this->never())
  566. ->method('send');
  567. $http = new Client([
  568. 'host' => 'cakephp.org',
  569. 'adapter' => $mock
  570. ]);
  571. $http->post('/projects/add', 'it works', ['type' => 'invalid']);
  572. }
  573. /**
  574. * Test that Client stores cookies
  575. *
  576. * @return void
  577. */
  578. public function testCookieStorage()
  579. {
  580. $adapter = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  581. ->setMethods(['send'])
  582. ->getMock();
  583. $headers = [
  584. 'HTTP/1.0 200 Ok',
  585. 'Set-Cookie: first=1',
  586. 'Set-Cookie: expiring=now; Expires=Wed, 09-Jun-1999 10:18:14 GMT'
  587. ];
  588. $response = new Response($headers, '');
  589. $adapter->expects($this->at(0))
  590. ->method('send')
  591. ->will($this->returnValue([$response]));
  592. $http = new Client([
  593. 'host' => 'cakephp.org',
  594. 'adapter' => $adapter,
  595. ]);
  596. $http->get('/projects');
  597. $cookies = $http->cookies();
  598. $this->assertCount(1, $cookies);
  599. $this->assertTrue($cookies->has('first'));
  600. $this->assertFalse($cookies->has('expiring'));
  601. }
  602. /**
  603. * Test cookieJar config option.
  604. *
  605. * @return void
  606. */
  607. public function testCookieJar()
  608. {
  609. $jar = new CookieCollection();
  610. $http = new Client([
  611. 'cookieJar' => $jar
  612. ]);
  613. $this->assertSame($jar, $http->cookies());
  614. }
  615. /**
  616. * Test addCookie() method.
  617. *
  618. * @return void
  619. */
  620. public function testAddCookie()
  621. {
  622. $client = new Client();
  623. $cookie = new Cookie('foo', '', null, '/', 'example.com');
  624. $this->assertFalse($client->cookies()->has('foo'));
  625. $client->addCookie($cookie);
  626. $this->assertTrue($client->cookies()->has('foo'));
  627. }
  628. /**
  629. * Test addCookie() method without a domain.
  630. *
  631. * @return void
  632. */
  633. public function testAddCookieWithoutDomain()
  634. {
  635. $this->expectException(\InvalidArgumentException::class);
  636. $this->expectExceptionMessage('Cookie must have a domain and a path set.');
  637. $client = new Client();
  638. $cookie = new Cookie('foo', '', null, '/', '');
  639. $this->assertFalse($client->cookies()->has('foo'));
  640. $client->addCookie($cookie);
  641. $this->assertTrue($client->cookies()->has('foo'));
  642. }
  643. /**
  644. * Test addCookie() method without a path.
  645. *
  646. * @return void
  647. */
  648. public function testAddCookieWithoutPath()
  649. {
  650. $this->expectException(\InvalidArgumentException::class);
  651. $this->expectExceptionMessage('Cookie must have a domain and a path set.');
  652. $client = new Client();
  653. $cookie = new Cookie('foo', '', null, '', 'example.com');
  654. $this->assertFalse($client->cookies()->has('foo'));
  655. $client->addCookie($cookie);
  656. $this->assertTrue($client->cookies()->has('foo'));
  657. }
  658. /**
  659. * test head request with querystring data
  660. *
  661. * @return void
  662. */
  663. public function testHeadQuerystring()
  664. {
  665. $response = new Response();
  666. $mock = $this->getMockBuilder('Cake\Http\Client\Adapter\Stream')
  667. ->setMethods(['send'])
  668. ->getMock();
  669. $mock->expects($this->once())
  670. ->method('send')
  671. ->with($this->callback(function ($request) {
  672. $this->assertInstanceOf('Cake\Http\Client\Request', $request);
  673. $this->assertEquals(Request::METHOD_HEAD, $request->getMethod());
  674. $this->assertEquals('http://cakephp.org/search?q=hi+there', '' . $request->getUri());
  675. return true;
  676. }))
  677. ->will($this->returnValue([$response]));
  678. $http = new Client([
  679. 'host' => 'cakephp.org',
  680. 'adapter' => $mock
  681. ]);
  682. $result = $http->head('/search', [
  683. 'q' => 'hi there',
  684. ]);
  685. $this->assertSame($result, $response);
  686. }
  687. /**
  688. * test redirects
  689. *
  690. * @return void
  691. */
  692. public function testRedirects()
  693. {
  694. $url = 'http://cakephp.org';
  695. $adapter = $this->getMockBuilder(Client\Adapter\Stream::class)
  696. ->setMethods(['send'])
  697. ->getMock();
  698. $redirect = new Response([
  699. 'HTTP/1.0 301',
  700. 'Location: http://cakephp.org/redirect1?foo=bar',
  701. 'Set-Cookie: redirect1=true;path=/',
  702. ]);
  703. $adapter->expects($this->at(0))
  704. ->method('send')
  705. ->with(
  706. $this->callback(function ($request) use ($url) {
  707. $this->assertInstanceOf(Request::class, $request);
  708. $this->assertEquals($url, $request->getUri());
  709. return true;
  710. }),
  711. $this->callback(function ($options) {
  712. $this->assertArrayNotHasKey('redirect', $options);
  713. return true;
  714. })
  715. )
  716. ->willReturn([$redirect]);
  717. $redirect2 = new Response([
  718. 'HTTP/1.0 301',
  719. 'Location: /redirect2#foo',
  720. 'Set-Cookie: redirect2=true;path=/',
  721. ]);
  722. $adapter->expects($this->at(1))
  723. ->method('send')
  724. ->with(
  725. $this->callback(function ($request) use ($url) {
  726. $this->assertInstanceOf(Request::class, $request);
  727. $this->assertEquals($url . '/redirect1?foo=bar', $request->getUri());
  728. return true;
  729. }),
  730. $this->callback(function ($options) {
  731. $this->assertArrayNotHasKey('redirect', $options);
  732. return true;
  733. })
  734. )
  735. ->willReturn([$redirect2]);
  736. $response = new Response([
  737. 'HTTP/1.0 200'
  738. ]);
  739. $adapter->expects($this->at(2))
  740. ->method('send')
  741. ->with($this->callback(function ($request) use ($url) {
  742. $this->assertInstanceOf(Request::class, $request);
  743. $this->assertEquals($url . '/redirect2#foo', $request->getUri());
  744. return true;
  745. }))
  746. ->willReturn([$response]);
  747. $client = new Client([
  748. 'adapter' => $adapter
  749. ]);
  750. $result = $client->send(new Request($url), [
  751. 'redirect' => 10
  752. ]);
  753. $this->assertInstanceOf(Response::class, $result);
  754. $this->assertTrue($result->isOk());
  755. $cookies = $client->cookies();
  756. $this->assertTrue($cookies->has('redirect1'));
  757. $this->assertTrue($cookies->has('redirect2'));
  758. }
  759. }