CurlTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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.7.0
  12. * @license https://opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Test\TestCase\Http\Client\Adapter;
  15. use Cake\Http\Client\Adapter\Curl;
  16. use Cake\Http\Client\Request;
  17. use Cake\Http\Client\Response;
  18. use Cake\TestSuite\TestCase;
  19. /**
  20. * HTTP curl adapter test.
  21. */
  22. class CurlTest extends TestCase
  23. {
  24. public function setUp()
  25. {
  26. parent::setUp();
  27. $this->skipIf(!function_exists('curl_init'), 'Skipping as ext/curl is not installed.');
  28. $this->curl = new Curl();
  29. $this->caFile = CORE_PATH . 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
  30. }
  31. /**
  32. * Test the send method
  33. *
  34. * @return void
  35. */
  36. public function testSendLive()
  37. {
  38. $request = new Request('http://localhost', 'GET', [
  39. 'User-Agent' => 'CakePHP TestSuite',
  40. 'Cookie' => 'testing=value',
  41. ]);
  42. try {
  43. $responses = $this->curl->send($request, []);
  44. } catch (\Cake\Core\Exception\Exception $e) {
  45. $this->markTestSkipped('Could not connect to localhost, skipping');
  46. }
  47. $this->assertCount(1, $responses);
  48. $response = $responses[0];
  49. $this->assertInstanceOf(Response::class, $response);
  50. $this->assertNotEmpty($response->getHeaders());
  51. $this->assertNotEmpty($response->getBody()->getContents());
  52. }
  53. /**
  54. * Test the send method
  55. *
  56. * @return void
  57. */
  58. public function testSendLiveResponseCheck()
  59. {
  60. $request = new Request('https://api.cakephp.org/3.0/', 'GET', [
  61. 'User-Agent' => 'CakePHP TestSuite',
  62. ]);
  63. try {
  64. $responses = $this->curl->send($request, []);
  65. } catch (\Cake\Core\Exception\Exception $e) {
  66. $this->markTestSkipped('Could not connect to book.cakephp.org, skipping');
  67. }
  68. $this->assertCount(1, $responses);
  69. $response = $responses[0];
  70. $this->assertInstanceOf(Response::class, $response);
  71. $this->assertTrue($response->hasHeader('Date'));
  72. $this->assertTrue($response->hasHeader('Content-type'));
  73. $this->assertContains('<html', $response->getBody()->getContents());
  74. }
  75. /**
  76. * Test converting client options into curl ones.
  77. *
  78. * @return void
  79. */
  80. public function testBuildOptionsGet()
  81. {
  82. $options = [
  83. 'timeout' => 5,
  84. ];
  85. $request = new Request(
  86. 'http://localhost/things',
  87. 'GET',
  88. ['Cookie' => 'testing=value']
  89. );
  90. $result = $this->curl->buildOptions($request, $options);
  91. $expected = [
  92. CURLOPT_URL => 'http://localhost/things',
  93. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  94. CURLOPT_RETURNTRANSFER => true,
  95. CURLOPT_HEADER => true,
  96. CURLOPT_HTTPHEADER => [
  97. 'Cookie: testing=value',
  98. 'Connection: close',
  99. 'User-Agent: CakePHP',
  100. ],
  101. CURLOPT_HTTPGET => true,
  102. CURLOPT_TIMEOUT => 5,
  103. CURLOPT_CAINFO => $this->caFile,
  104. ];
  105. $this->assertSame($expected, $result);
  106. }
  107. /**
  108. * Test converting client options into curl ones.
  109. *
  110. * @return void
  111. */
  112. public function testBuildOptionsGetWithBody()
  113. {
  114. $options = [
  115. 'timeout' => 5,
  116. ];
  117. $request = new Request(
  118. 'http://localhost/things',
  119. 'GET',
  120. ['Cookie' => 'testing=value'],
  121. '{"some":"body"}'
  122. );
  123. $result = $this->curl->buildOptions($request, $options);
  124. $expected = [
  125. CURLOPT_URL => 'http://localhost/things',
  126. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  127. CURLOPT_RETURNTRANSFER => true,
  128. CURLOPT_HEADER => true,
  129. CURLOPT_HTTPHEADER => [
  130. 'Cookie: testing=value',
  131. 'Connection: close',
  132. 'User-Agent: CakePHP',
  133. ],
  134. CURLOPT_HTTPGET => true,
  135. CURLOPT_POSTFIELDS => '{"some":"body"}',
  136. CURLOPT_CUSTOMREQUEST => 'get',
  137. CURLOPT_TIMEOUT => 5,
  138. CURLOPT_CAINFO => $this->caFile,
  139. ];
  140. $this->assertSame($expected, $result);
  141. }
  142. /**
  143. * Test converting client options into curl ones.
  144. *
  145. * @return void
  146. */
  147. public function testBuildOptionsPost()
  148. {
  149. $options = [];
  150. $request = new Request(
  151. 'http://localhost/things',
  152. 'POST',
  153. ['Cookie' => 'testing=value'],
  154. ['name' => 'cakephp', 'yes' => 1]
  155. );
  156. $result = $this->curl->buildOptions($request, $options);
  157. $expected = [
  158. CURLOPT_URL => 'http://localhost/things',
  159. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  160. CURLOPT_RETURNTRANSFER => true,
  161. CURLOPT_HEADER => true,
  162. CURLOPT_HTTPHEADER => [
  163. 'Cookie: testing=value',
  164. 'Connection: close',
  165. 'User-Agent: CakePHP',
  166. 'Content-Type: application/x-www-form-urlencoded',
  167. ],
  168. CURLOPT_POST => true,
  169. CURLOPT_POSTFIELDS => 'name=cakephp&yes=1',
  170. CURLOPT_CAINFO => $this->caFile,
  171. ];
  172. $this->assertSame($expected, $result);
  173. }
  174. /**
  175. * Test converting client options into curl ones.
  176. *
  177. * @return void
  178. */
  179. public function testBuildOptionsPut()
  180. {
  181. $options = [];
  182. $request = new Request(
  183. 'http://localhost/things',
  184. 'PUT',
  185. ['Cookie' => 'testing=value']
  186. );
  187. $result = $this->curl->buildOptions($request, $options);
  188. $expected = [
  189. CURLOPT_URL => 'http://localhost/things',
  190. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  191. CURLOPT_RETURNTRANSFER => true,
  192. CURLOPT_HEADER => true,
  193. CURLOPT_HTTPHEADER => [
  194. 'Cookie: testing=value',
  195. 'Connection: close',
  196. 'User-Agent: CakePHP',
  197. ],
  198. CURLOPT_POST => true,
  199. CURLOPT_CUSTOMREQUEST => 'PUT',
  200. CURLOPT_CAINFO => $this->caFile,
  201. ];
  202. $this->assertSame($expected, $result);
  203. }
  204. /**
  205. * Test converting client options into curl ones.
  206. *
  207. * @return void
  208. */
  209. public function testBuildOptionsJsonPost()
  210. {
  211. $options = [];
  212. $content = json_encode(['a' => 1, 'b' => 2]);
  213. $request = new Request(
  214. 'http://localhost/things',
  215. 'POST',
  216. ['Content-type' => 'application/json'],
  217. $content
  218. );
  219. $result = $this->curl->buildOptions($request, $options);
  220. $expected = [
  221. CURLOPT_URL => 'http://localhost/things',
  222. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  223. CURLOPT_RETURNTRANSFER => true,
  224. CURLOPT_HEADER => true,
  225. CURLOPT_HTTPHEADER => [
  226. 'Content-type: application/json',
  227. 'Connection: close',
  228. 'User-Agent: CakePHP',
  229. ],
  230. CURLOPT_POST => true,
  231. CURLOPT_POSTFIELDS => $content,
  232. CURLOPT_CAINFO => $this->caFile,
  233. ];
  234. $this->assertSame($expected, $result);
  235. }
  236. /**
  237. * Test converting client options into curl ones.
  238. *
  239. * @return void
  240. */
  241. public function testBuildOptionsSsl()
  242. {
  243. $options = [
  244. 'ssl_verify_host' => true,
  245. 'ssl_verify_peer' => true,
  246. 'ssl_verify_peer_name' => true,
  247. // These options do nothing in curl.
  248. 'ssl_verify_depth' => 9000,
  249. 'ssl_allow_self_signed' => false,
  250. ];
  251. $request = new Request('http://localhost/things', 'GET');
  252. $result = $this->curl->buildOptions($request, $options);
  253. $expected = [
  254. CURLOPT_URL => 'http://localhost/things',
  255. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  256. CURLOPT_RETURNTRANSFER => true,
  257. CURLOPT_HEADER => true,
  258. CURLOPT_HTTPHEADER => [
  259. 'Connection: close',
  260. 'User-Agent: CakePHP',
  261. ],
  262. CURLOPT_HTTPGET => true,
  263. CURLOPT_SSL_VERIFYPEER => true,
  264. CURLOPT_SSL_VERIFYHOST => 2,
  265. CURLOPT_CAINFO => $this->caFile,
  266. ];
  267. $this->assertSame($expected, $result);
  268. }
  269. /**
  270. * Test converting client options into curl ones.
  271. *
  272. * @return void
  273. */
  274. public function testBuildOptionsProxy()
  275. {
  276. $options = [
  277. 'proxy' => [
  278. 'proxy' => '127.0.0.1:8080',
  279. 'username' => 'frodo',
  280. 'password' => 'one_ring',
  281. ],
  282. ];
  283. $request = new Request('http://localhost/things', 'GET');
  284. $result = $this->curl->buildOptions($request, $options);
  285. $expected = [
  286. CURLOPT_URL => 'http://localhost/things',
  287. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  288. CURLOPT_RETURNTRANSFER => true,
  289. CURLOPT_HEADER => true,
  290. CURLOPT_HTTPHEADER => [
  291. 'Connection: close',
  292. 'User-Agent: CakePHP',
  293. ],
  294. CURLOPT_HTTPGET => true,
  295. CURLOPT_CAINFO => $this->caFile,
  296. CURLOPT_PROXY => '127.0.0.1:8080',
  297. CURLOPT_PROXYUSERPWD => 'frodo:one_ring',
  298. ];
  299. $this->assertSame($expected, $result);
  300. }
  301. /**
  302. * Test converting client options into curl ones.
  303. *
  304. * @return void
  305. */
  306. public function testBuildOptionsHead()
  307. {
  308. $options = [];
  309. $request = new Request(
  310. 'http://localhost/things',
  311. 'HEAD',
  312. ['Cookie' => 'testing=value']
  313. );
  314. $result = $this->curl->buildOptions($request, $options);
  315. $expected = [
  316. CURLOPT_URL => 'http://localhost/things',
  317. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  318. CURLOPT_RETURNTRANSFER => true,
  319. CURLOPT_HEADER => true,
  320. CURLOPT_HTTPHEADER => [
  321. 'Cookie: testing=value',
  322. 'Connection: close',
  323. 'User-Agent: CakePHP',
  324. ],
  325. CURLOPT_NOBODY => true,
  326. CURLOPT_CAINFO => $this->caFile,
  327. ];
  328. $this->assertSame($expected, $result);
  329. }
  330. /**
  331. * Test converting client options into curl ones.
  332. *
  333. * @return void
  334. */
  335. public function testBuildOptionsCurlOptions()
  336. {
  337. $options = [
  338. 'curl' => [
  339. CURLOPT_USERAGENT => 'Super-secret',
  340. ],
  341. ];
  342. $request = new Request('http://localhost/things', 'GET');
  343. $request = $request->withProtocolVersion('1.0');
  344. $result = $this->curl->buildOptions($request, $options);
  345. $expected = [
  346. CURLOPT_URL => 'http://localhost/things',
  347. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
  348. CURLOPT_RETURNTRANSFER => true,
  349. CURLOPT_HEADER => true,
  350. CURLOPT_HTTPHEADER => [
  351. 'Connection: close',
  352. 'User-Agent: CakePHP',
  353. ],
  354. CURLOPT_HTTPGET => true,
  355. CURLOPT_CAINFO => $this->caFile,
  356. CURLOPT_USERAGENT => 'Super-secret',
  357. ];
  358. $this->assertSame($expected, $result);
  359. }
  360. /**
  361. * Test converting client options into curl ones.
  362. *
  363. * @return void
  364. */
  365. public function testBuildOptionsProtocolVersion()
  366. {
  367. $this->skipIf(!defined('CURL_HTTP_VERSION_2TLS'), 'Requires libcurl 7.42');
  368. $options = [];
  369. $request = new Request('http://localhost/things', 'GET');
  370. $request = $request->withProtocolVersion('2');
  371. $result = $this->curl->buildOptions($request, $options);
  372. $this->assertSame(CURL_HTTP_VERSION_2TLS, $result[CURLOPT_HTTP_VERSION]);
  373. }
  374. }