CurlTest.php 12 KB

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