base.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <?php
  2. /**
  3. * Note, When running these tests, remember that some things are done differently
  4. * based on safe_mode. You can run the test in safe_mode like such:
  5. *
  6. * phpunit -d safe_mode=on --group http
  7. *
  8. * You may also need `-d safe_mode_gid=1` to relax the safe_mode checks to allow
  9. * inclusion of PEAR.
  10. *
  11. * The WP_HTTP tests require a class-http.php file of r17550 or later.
  12. */
  13. abstract class WP_HTTP_UnitTestCase extends WP_UnitTestCase {
  14. // You can use your own version of data/WPHTTP-testcase-redirection-script.php here.
  15. public $redirection_script = 'http://api.wordpress.org/core/tests/1.0/redirection.php';
  16. public $file_stream_url = 'http://s.w.org/screenshots/3.9/dashboard.png';
  17. protected $http_request_args;
  18. function setUp() {
  19. parent::setUp();
  20. if ( is_callable( array( 'WP_Http', '_getTransport' ) ) ) {
  21. $this->markTestSkipped( 'The WP_Http tests require a class-http.php file of r17550 or later.' );
  22. return;
  23. }
  24. $class = 'WP_Http_' . ucfirst( $this->transport );
  25. if ( ! call_user_func( array( $class, 'test' ) ) ) {
  26. $this->markTestSkipped( sprintf( 'The transport %s is not supported on this system.', $this->transport ) );
  27. }
  28. // Disable all transports aside from this one.
  29. foreach ( array( 'curl', 'streams', 'fsockopen' ) as $t ) {
  30. remove_filter( "use_{$t}_transport", '__return_false' ); // Just strip them all...
  31. if ( $t !== $this->transport ) {
  32. add_filter( "use_{$t}_transport", '__return_false' ); // ...and add it back if need be.
  33. }
  34. }
  35. }
  36. function filter_http_request_args( array $args ) {
  37. $this->http_request_args = $args;
  38. return $args;
  39. }
  40. /**
  41. * @covers ::wp_remote_request
  42. */
  43. function test_redirect_on_301() {
  44. // 5 : 5 & 301.
  45. $res = wp_remote_request( $this->redirection_script . '?code=301&rt=' . 5, array( 'redirection' => 5 ) );
  46. $this->skipTestOnTimeout( $res );
  47. $this->assertNotWPError( $res );
  48. $this->assertSame( 200, (int) $res['response']['code'] );
  49. }
  50. /**
  51. * @covers ::wp_remote_request
  52. */
  53. function test_redirect_on_302() {
  54. // 5 : 5 & 302.
  55. $res = wp_remote_request( $this->redirection_script . '?code=302&rt=' . 5, array( 'redirection' => 5 ) );
  56. $this->skipTestOnTimeout( $res );
  57. $this->assertNotWPError( $res );
  58. $this->assertSame( 200, (int) $res['response']['code'] );
  59. }
  60. /**
  61. * @ticket 16855
  62. *
  63. * @covers ::wp_remote_request
  64. */
  65. function test_redirect_on_301_no_redirect() {
  66. // 5 > 0 & 301.
  67. $res = wp_remote_request( $this->redirection_script . '?code=301&rt=' . 5, array( 'redirection' => 0 ) );
  68. $this->skipTestOnTimeout( $res );
  69. $this->assertNotWPError( $res );
  70. $this->assertSame( 301, (int) $res['response']['code'] );
  71. }
  72. /**
  73. * @ticket 16855
  74. *
  75. * @covers ::wp_remote_request
  76. */
  77. function test_redirect_on_302_no_redirect() {
  78. // 5 > 0 & 302.
  79. $res = wp_remote_request( $this->redirection_script . '?code=302&rt=' . 5, array( 'redirection' => 0 ) );
  80. $this->skipTestOnTimeout( $res );
  81. $this->assertNotWPError( $res );
  82. $this->assertSame( 302, (int) $res['response']['code'] );
  83. }
  84. /**
  85. * @covers ::wp_remote_request
  86. */
  87. function test_redirections_equal() {
  88. // 5 - 5.
  89. $res = wp_remote_request( $this->redirection_script . '?rt=' . 5, array( 'redirection' => 5 ) );
  90. $this->skipTestOnTimeout( $res );
  91. $this->assertNotWPError( $res );
  92. $this->assertSame( 200, (int) $res['response']['code'] );
  93. }
  94. /**
  95. * @covers ::wp_remote_request
  96. */
  97. function test_no_head_redirections() {
  98. // No redirections on HEAD request.
  99. $res = wp_remote_request( $this->redirection_script . '?code=302&rt=' . 1, array( 'method' => 'HEAD' ) );
  100. $this->skipTestOnTimeout( $res );
  101. $this->assertNotWPError( $res );
  102. $this->assertSame( 302, (int) $res['response']['code'] );
  103. }
  104. /**
  105. * @ticket 16855
  106. *
  107. * @covers ::wp_remote_request
  108. */
  109. function test_redirect_on_head() {
  110. // Redirections on HEAD request when Requested.
  111. $res = wp_remote_request(
  112. $this->redirection_script . '?rt=' . 5,
  113. array(
  114. 'redirection' => 5,
  115. 'method' => 'HEAD',
  116. )
  117. );
  118. $this->skipTestOnTimeout( $res );
  119. $this->assertNotWPError( $res );
  120. $this->assertSame( 200, (int) $res['response']['code'] );
  121. }
  122. /**
  123. * @covers ::wp_remote_request
  124. */
  125. function test_redirections_greater() {
  126. // 10 > 5.
  127. $res = wp_remote_request( $this->redirection_script . '?rt=' . 10, array( 'redirection' => 5 ) );
  128. $this->skipTestOnTimeout( $res );
  129. $this->assertWPError( $res );
  130. }
  131. /**
  132. * @covers ::wp_remote_request
  133. */
  134. function test_redirections_greater_edgecase() {
  135. // 6 > 5 (close edge case).
  136. $res = wp_remote_request( $this->redirection_script . '?rt=' . 6, array( 'redirection' => 5 ) );
  137. $this->skipTestOnTimeout( $res );
  138. $this->assertWPError( $res );
  139. }
  140. /**
  141. * @covers ::wp_remote_request
  142. */
  143. function test_redirections_less_edgecase() {
  144. // 4 < 5 (close edge case).
  145. $res = wp_remote_request( $this->redirection_script . '?rt=' . 4, array( 'redirection' => 5 ) );
  146. $this->skipTestOnTimeout( $res );
  147. $this->assertNotWPError( $res );
  148. }
  149. /**
  150. * @ticket 16855
  151. *
  152. * @covers ::wp_remote_request
  153. */
  154. function test_redirections_zero_redirections_specified() {
  155. // 0 redirections asked for, should return the document?
  156. $res = wp_remote_request( $this->redirection_script . '?code=302&rt=' . 5, array( 'redirection' => 0 ) );
  157. $this->skipTestOnTimeout( $res );
  158. $this->assertNotWPError( $res );
  159. $this->assertSame( 302, (int) $res['response']['code'] );
  160. }
  161. /**
  162. * Do not redirect on non 3xx status codes.
  163. *
  164. * @ticket 16889
  165. *
  166. * @covers ::wp_remote_request
  167. */
  168. function test_location_header_on_201() {
  169. // Prints PASS on initial load, FAIL if the client follows the specified redirection.
  170. $res = wp_remote_request( $this->redirection_script . '?201-location=true' );
  171. $this->skipTestOnTimeout( $res );
  172. $this->assertNotWPError( $res );
  173. $this->assertSame( 'PASS', $res['body'] );
  174. }
  175. /**
  176. * Test handling of PUT requests on redirects.
  177. *
  178. * @ticket 16889
  179. *
  180. * @covers ::wp_remote_request
  181. * @covers ::wp_remote_retrieve_body
  182. */
  183. function test_no_redirection_on_PUT() {
  184. $url = 'http://api.wordpress.org/core/tests/1.0/redirection.php?201-location=1';
  185. // Test 301 - POST to POST.
  186. $res = wp_remote_request(
  187. $url,
  188. array(
  189. 'method' => 'PUT',
  190. 'timeout' => 30,
  191. )
  192. );
  193. $this->skipTestOnTimeout( $res );
  194. $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) );
  195. $this->assertTrue( ! empty( $res['headers']['location'] ) );
  196. }
  197. /**
  198. * @ticket 11888
  199. *
  200. * @covers ::wp_remote_request
  201. */
  202. function test_send_headers() {
  203. // Test that the headers sent are received by the server.
  204. $headers = array(
  205. 'test1' => 'test',
  206. 'test2' => 0,
  207. 'test3' => '',
  208. );
  209. $res = wp_remote_request( $this->redirection_script . '?header-check', array( 'headers' => $headers ) );
  210. $this->skipTestOnTimeout( $res );
  211. $this->assertNotWPError( $res );
  212. $headers = array();
  213. foreach ( explode( "\n", $res['body'] ) as $key => $value ) {
  214. if ( empty( $value ) ) {
  215. continue;
  216. }
  217. $parts = explode( ':', $value, 2 );
  218. unset( $headers[ $key ] );
  219. $headers[ $parts[0] ] = $parts[1];
  220. }
  221. $this->assertTrue( isset( $headers['test1'] ) && 'test' === $headers['test1'] );
  222. $this->assertTrue( isset( $headers['test2'] ) && '0' === $headers['test2'] );
  223. // cURL/HTTP Extension Note: Will never pass, cURL does not pass headers with an empty value.
  224. // Should it be that empty headers with empty values are NOT sent?
  225. // $this->assertTrue( isset( $headers['test3'] ) && '' === $headers['test3'] );
  226. }
  227. /**
  228. * @covers ::wp_remote_request
  229. */
  230. function test_file_stream() {
  231. $url = $this->file_stream_url;
  232. $size = 153204;
  233. $res = wp_remote_request(
  234. $url,
  235. array(
  236. 'stream' => true,
  237. 'timeout' => 30,
  238. )
  239. ); // Auto generate the filename.
  240. // Cleanup before we assert, as it'll return early.
  241. if ( ! is_wp_error( $res ) ) {
  242. $filesize = filesize( $res['filename'] );
  243. unlink( $res['filename'] );
  244. }
  245. $this->skipTestOnTimeout( $res );
  246. $this->assertNotWPError( $res );
  247. $this->assertSame( '', $res['body'] ); // The body should be empty.
  248. $this->assertEquals( $size, $res['headers']['content-length'] ); // Check the headers are returned (and the size is the same).
  249. $this->assertSame( $size, $filesize ); // Check that the file is written to disk correctly without any extra characters.
  250. $this->assertStringStartsWith( get_temp_dir(), $res['filename'] ); // Check it's saving within the temp directory.
  251. }
  252. /**
  253. * @ticket 26726
  254. *
  255. * @covers ::wp_remote_request
  256. */
  257. function test_file_stream_limited_size() {
  258. $url = $this->file_stream_url;
  259. $size = 10000;
  260. $res = wp_remote_request(
  261. $url,
  262. array(
  263. 'stream' => true,
  264. 'timeout' => 30,
  265. 'limit_response_size' => $size,
  266. )
  267. ); // Auto generate the filename.
  268. // Cleanup before we assert, as it'll return early.
  269. if ( ! is_wp_error( $res ) ) {
  270. $filesize = filesize( $res['filename'] );
  271. unlink( $res['filename'] );
  272. }
  273. $this->skipTestOnTimeout( $res );
  274. $this->assertNotWPError( $res );
  275. $this->assertSame( $size, $filesize ); // Check that the file is written to disk correctly without any extra characters.
  276. }
  277. /**
  278. * Tests limiting the response size when returning strings.
  279. *
  280. * @ticket 31172
  281. *
  282. * @covers ::wp_remote_request
  283. */
  284. function test_request_limited_size() {
  285. $url = $this->file_stream_url;
  286. $size = 10000;
  287. $res = wp_remote_request(
  288. $url,
  289. array(
  290. 'timeout' => 30,
  291. 'limit_response_size' => $size,
  292. )
  293. );
  294. $this->skipTestOnTimeout( $res );
  295. $this->assertNotWPError( $res );
  296. $this->assertSame( $size, strlen( $res['body'] ) );
  297. }
  298. /**
  299. * Test POST redirection methods.
  300. *
  301. * @dataProvider data_post_redirect_to_method_300
  302. *
  303. * @ticket 17588
  304. *
  305. * @covers ::wp_remote_post
  306. * @covers ::wp_remote_retrieve_body
  307. */
  308. function test_post_redirect_to_method_300( $response_code, $method ) {
  309. $url = 'http://api.wordpress.org/core/tests/1.0/redirection.php?post-redirect-to-method=1';
  310. $res = wp_remote_post( add_query_arg( 'response_code', $response_code, $url ), array( 'timeout' => 30 ) );
  311. $this->skipTestOnTimeout( $res );
  312. $this->assertSame( $method, wp_remote_retrieve_body( $res ) );
  313. }
  314. public function data_post_redirect_to_method_300() {
  315. return array(
  316. // Test 300 - POST to POST.
  317. array(
  318. 300,
  319. 'POST',
  320. ),
  321. // Test 301 - POST to POST.
  322. array(
  323. 301,
  324. 'POST',
  325. ),
  326. // Test 302 - POST to GET.
  327. array(
  328. 302,
  329. 'GET',
  330. ),
  331. // Test 303 - POST to GET.
  332. array(
  333. 303,
  334. 'GET',
  335. ),
  336. );
  337. }
  338. /**
  339. * Test HTTP Requests using an IP URL, with a HOST header specified.
  340. *
  341. * @ticket 24182
  342. *
  343. * @covers ::wp_remote_get
  344. * @covers ::wp_remote_retrieve_body
  345. */
  346. function test_ip_url_with_host_header() {
  347. $ip = gethostbyname( 'api.wordpress.org' );
  348. $url = 'http://' . $ip . '/core/tests/1.0/redirection.php?print-pass=1';
  349. $args = array(
  350. 'headers' => array(
  351. 'Host' => 'api.wordpress.org',
  352. ),
  353. 'timeout' => 30,
  354. 'redirection' => 0,
  355. );
  356. $res = wp_remote_get( $url, $args );
  357. $this->skipTestOnTimeout( $res );
  358. $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) );
  359. }
  360. /**
  361. * Test HTTP requests where SSL verification is disabled but the CA bundle is still populated.
  362. *
  363. * @ticket 33978
  364. *
  365. * @covers ::wp_remote_head
  366. */
  367. function test_https_url_without_ssl_verification() {
  368. $url = 'https://wordpress.org/';
  369. $args = array(
  370. 'sslverify' => false,
  371. );
  372. add_filter( 'http_request_args', array( $this, 'filter_http_request_args' ) );
  373. $res = wp_remote_head( $url, $args );
  374. remove_filter( 'http_request_args', array( $this, 'filter_http_request_args' ) );
  375. $this->skipTestOnTimeout( $res );
  376. $this->assertNotEmpty( $this->http_request_args['sslcertificates'] );
  377. $this->assertNotWPError( $res );
  378. }
  379. /**
  380. * Test HTTP Redirects with multiple Location headers specified.
  381. *
  382. * @ticket 16890
  383. *
  384. * @covers ::wp_remote_head
  385. * @covers ::wp_remote_retrieve_header
  386. * @covers ::wp_remote_get
  387. * @covers ::wp_remote_retrieve_body
  388. */
  389. function test_multiple_location_headers() {
  390. $url = 'http://api.wordpress.org/core/tests/1.0/redirection.php?multiple-location-headers=1';
  391. $res = wp_remote_head( $url, array( 'timeout' => 30 ) );
  392. $this->skipTestOnTimeout( $res );
  393. $this->assertInternalType( 'array', wp_remote_retrieve_header( $res, 'location' ) );
  394. $this->assertCount( 2, wp_remote_retrieve_header( $res, 'location' ) );
  395. $res = wp_remote_get( $url, array( 'timeout' => 30 ) );
  396. $this->skipTestOnTimeout( $res );
  397. $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) );
  398. }
  399. /**
  400. * Test HTTP Cookie handling.
  401. *
  402. * @ticket 21182
  403. *
  404. * @covers ::wp_remote_get
  405. * @covers ::wp_remote_retrieve_body
  406. */
  407. function test_cookie_handling() {
  408. $url = 'http://api.wordpress.org/core/tests/1.0/redirection.php?cookie-test=1';
  409. $res = wp_remote_get( $url );
  410. $this->skipTestOnTimeout( $res );
  411. $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) );
  412. }
  413. /**
  414. * Test if HTTPS support works.
  415. *
  416. * @group ssl
  417. * @ticket 25007
  418. *
  419. * @covers ::wp_remote_get
  420. */
  421. function test_ssl() {
  422. if ( ! wp_http_supports( array( 'ssl' ) ) ) {
  423. $this->fail( 'This installation of PHP does not support SSL.' );
  424. }
  425. $res = wp_remote_get( 'https://wordpress.org/' );
  426. $this->skipTestOnTimeout( $res );
  427. $this->assertNotWPError( $res );
  428. }
  429. /**
  430. * @ticket 37733
  431. *
  432. * @covers ::wp_remote_request
  433. */
  434. function test_url_with_double_slashes_path() {
  435. $url = $this->redirection_script . '?rt=' . 0;
  436. $path = parse_url( $url, PHP_URL_PATH );
  437. $url = str_replace( $path, '/' . $path, $url );
  438. $res = wp_remote_request( $url );
  439. $this->skipTestOnTimeout( $res );
  440. $this->assertNotWPError( $res );
  441. }
  442. }