Changeset 65320
- Timestamp:
- 11/06/2026 08:43:25 PM (less than one hour ago)
- Location:
- trunk/tests/phpunit/tests/http
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/http/base.php
r65084 r65320 12 12 */ 13 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'; 14 /** 15 * URL of the local redirection fixture (set in set_up() when available). 16 * 17 * Prefer the local PHP built-in server fixture. Tests that need redirection 18 * coverage must call require_redirection_fixture() so missing fixtures skip 19 * or fail instead of falling back to a live api.wordpress.org request. 20 * 21 * @var string 22 */ 23 public $redirection_script = ''; 16 24 17 25 /** … … 71 79 private static $file_stream_fixture_fail_reason = null; 72 80 81 /** 82 * Captured HTTP request args from the most recent filtered request. 83 * 84 * @var array 85 */ 73 86 protected $http_request_args; 87 88 /** 89 * Captured Requests options from the most recent intercepted request. 90 * 91 * @var array 92 */ 93 protected $requests_options = array(); 74 94 75 95 /** … … 297 317 } 298 318 299 public function filter_http_request_args( array $args ) { 300 $this->http_request_args = $args; 301 return $args; 319 /** 320 * Allows only this class's local HTTP fixture through the external-HTTP guard. 321 * 322 * Other tests continue to use the parent blocker for any non-mocked request. 323 * 324 * @param false|array|WP_Error $response A preemptive response, or false when none was given. 325 * @param array $args Request arguments. 326 * @param string $url The request URL. 327 * @return false|array|WP_Error The preemptive response, or an error for a blocked request. 328 */ 329 public function block_external_http_request( $response, array $args, string $url ) { 330 if ( false === $response && $this->is_fixture_url( $url ) ) { 331 if ( ! has_action( 'requests-requests.before_redirect', array( $this, 'block_external_fixture_redirect' ) ) ) { 332 add_action( 'requests-requests.before_redirect', array( $this, 'block_external_fixture_redirect' ), 10, 5 ); 333 } 334 335 return $response; 336 } 337 338 return parent::block_external_http_request( $response, $args, $url ); 339 } 340 341 /** 342 * Whether a URL targets this class's local fixture server host and port. 343 * 344 * @param string $url Request URL. 345 * @return bool True when the URL matches the fixture host and port. 346 */ 347 protected function is_fixture_url( string $url ): bool { 348 if ( ! self::$file_stream_fixture_url ) { 349 return false; 350 } 351 352 $fixture_host = wp_parse_url( self::$file_stream_fixture_url, PHP_URL_HOST ); 353 $fixture_port = wp_parse_url( self::$file_stream_fixture_url, PHP_URL_PORT ); 354 $host = wp_parse_url( $url, PHP_URL_HOST ); 355 $port = wp_parse_url( $url, PHP_URL_PORT ); 356 357 return is_string( $fixture_host ) 358 && is_string( $host ) 359 && strtolower( $fixture_host ) === strtolower( $host ) 360 && (int) $fixture_port === (int) $port; 361 } 362 363 /** 364 * Blocks redirects from the local fixture to non-fixture URLs. 365 * 366 * Defensive only: the current redirection fixture never leaves this host/port, 367 * so this callback is not exercised by existing tests. 368 * 369 * @throws WpOrg\Requests\Exception When the redirect target leaves the fixture server. 370 * 371 * @param string $location Redirect location (passed by reference by Requests). 372 * @param array $req_headers Request headers. 373 * @param array|null $req_data Request data. 374 * @param array $options Requests options. 375 * @param WpOrg\Requests\Response $response Response that triggered the redirect. 376 */ 377 public function block_external_fixture_redirect( &$location, &$req_headers, &$req_data, &$options, $response ) { 378 if ( $this->is_fixture_url( $location ) ) { 379 return; 380 } 381 382 $this->blocked_http_requests[] = $location; 383 384 throw new WpOrg\Requests\Exception( 385 'External HTTP redirects are blocked in tests that are not in the `external-http` group.', 386 'test_external_http_blocked' 387 ); 302 388 } 303 389 … … 307 393 public function test_redirect_on_301() { 308 394 // 5 : 5 & 301. 309 $res = $this->wp_remote_request( $this-> redirection_script. '?code=301&rt=' . 5, array( 'redirection' => 5 ) );395 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=301&rt=' . 5, array( 'redirection' => 5 ) ); 310 396 311 397 $this->assertNotWPError( $res ); … … 318 404 public function test_redirect_on_302() { 319 405 // 5 : 5 & 302. 320 $res = $this->wp_remote_request( $this-> redirection_script. '?code=302&rt=' . 5, array( 'redirection' => 5 ) );406 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=302&rt=' . 5, array( 'redirection' => 5 ) ); 321 407 322 408 $this->assertNotWPError( $res ); … … 331 417 public function test_redirect_on_301_no_redirect() { 332 418 // 5 > 0 & 301. 333 $res = $this->wp_remote_request( $this-> redirection_script. '?code=301&rt=' . 5, array( 'redirection' => 0 ) );419 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=301&rt=' . 5, array( 'redirection' => 0 ) ); 334 420 335 421 $this->assertNotWPError( $res ); … … 344 430 public function test_redirect_on_302_no_redirect() { 345 431 // 5 > 0 & 302. 346 $res = $this->wp_remote_request( $this-> redirection_script. '?code=302&rt=' . 5, array( 'redirection' => 0 ) );432 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=302&rt=' . 5, array( 'redirection' => 0 ) ); 347 433 348 434 $this->assertNotWPError( $res ); … … 355 441 public function test_redirections_equal() { 356 442 // 5 - 5. 357 $res = $this->wp_remote_request( $this-> redirection_script. '?rt=' . 5, array( 'redirection' => 5 ) );443 $res = $this->wp_remote_request( $this->get_redirection_script() . '?rt=' . 5, array( 'redirection' => 5 ) ); 358 444 359 445 $this->assertNotWPError( $res ); … … 366 452 public function test_no_head_redirections() { 367 453 // No redirections on HEAD request. 368 $res = $this->wp_remote_request( $this-> redirection_script. '?code=302&rt=' . 1, array( 'method' => 'HEAD' ) );454 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=302&rt=' . 1, array( 'method' => 'HEAD' ) ); 369 455 370 456 $this->assertNotWPError( $res ); … … 380 466 // Redirections on HEAD request when Requested. 381 467 $res = $this->wp_remote_request( 382 $this-> redirection_script. '?rt=' . 5,468 $this->get_redirection_script() . '?rt=' . 5, 383 469 array( 384 470 'redirection' => 5, … … 396 482 public function test_redirections_greater() { 397 483 // 10 > 5. 398 $res = $this->wp_remote_request( $this-> redirection_script. '?rt=' . 10, array( 'redirection' => 5 ) );484 $res = $this->wp_remote_request( $this->get_redirection_script() . '?rt=' . 10, array( 'redirection' => 5 ) ); 399 485 400 486 $this->assertWPError( $res ); … … 406 492 public function test_redirections_greater_edgecase() { 407 493 // 6 > 5 (close edge case). 408 $res = $this->wp_remote_request( $this-> redirection_script. '?rt=' . 6, array( 'redirection' => 5 ) );494 $res = $this->wp_remote_request( $this->get_redirection_script() . '?rt=' . 6, array( 'redirection' => 5 ) ); 409 495 410 496 $this->assertWPError( $res ); … … 416 502 public function test_redirections_less_edgecase() { 417 503 // 4 < 5 (close edge case). 418 $res = $this->wp_remote_request( $this-> redirection_script. '?rt=' . 4, array( 'redirection' => 5 ) );504 $res = $this->wp_remote_request( $this->get_redirection_script() . '?rt=' . 4, array( 'redirection' => 5 ) ); 419 505 420 506 $this->assertNotWPError( $res ); … … 428 514 public function test_redirections_zero_redirections_specified() { 429 515 // 0 redirections asked for, should return the document? 430 $res = $this->wp_remote_request( $this-> redirection_script. '?code=302&rt=' . 5, array( 'redirection' => 0 ) );516 $res = $this->wp_remote_request( $this->get_redirection_script() . '?code=302&rt=' . 5, array( 'redirection' => 0 ) ); 431 517 432 518 $this->assertNotWPError( $res ); … … 443 529 public function test_location_header_on_201() { 444 530 // Prints PASS on initial load, FAIL if the client follows the specified redirection. 445 $res = $this->wp_remote_request( $this-> redirection_script. '?201-location=true' );531 $res = $this->wp_remote_request( $this->get_redirection_script() . '?201-location=true' ); 446 532 447 533 $this->assertNotWPError( $res ); … … 458 544 */ 459 545 public function test_no_redirection_on_PUT() { 460 $url = $this-> redirection_script. '?201-location=1';546 $url = $this->get_redirection_script() . '?201-location=1'; 461 547 462 548 // Test 301 - POST to POST. … … 511 597 'test3' => '', 512 598 ); 513 $res = $this->wp_remote_request( $this-> redirection_script. '?header-check', array( 'headers' => $headers ) );599 $res = $this->wp_remote_request( $this->get_redirection_script() . '?header-check', array( 'headers' => $headers ) ); 514 600 515 601 $this->assertNotWPError( $res ); … … 547 633 548 634 $this->fail( 'The local HTTP stream fixture server was not started.' ); 635 } 636 637 /** 638 * Ensures the local redirection fixture server is available. 639 * 640 * Skips when a prerequisite is missing. Fails with a diagnostic when 641 * fixture startup failed unexpectedly. Does not fall back to the live 642 * api.wordpress.org redirection script. 643 * 644 * @ticket 63914 645 */ 646 protected function require_redirection_fixture() { 647 if ( ! empty( $this->redirection_script ) ) { 648 return; 649 } 650 651 if ( self::$file_stream_fixture_skip_reason ) { 652 $this->markTestSkipped( self::$file_stream_fixture_skip_reason ); 653 } 654 655 if ( self::$file_stream_fixture_fail_reason ) { 656 $this->fail( self::$file_stream_fixture_fail_reason ); 657 } 658 659 $this->fail( 'The local HTTP redirection fixture server was not started.' ); 660 } 661 662 /** 663 * Returns the local redirection fixture URL, requiring it first. 664 * 665 * @ticket 63914 666 * 667 * @return string Local redirection fixture URL. 668 */ 669 protected function get_redirection_script() { 670 $this->require_redirection_fixture(); 671 return $this->redirection_script; 549 672 } 550 673 … … 647 770 */ 648 771 public function test_post_redirect_to_method_300( $response_code, $method ) { 649 $url = $this-> redirection_script. '?post-redirect-to-method=1';772 $url = $this->get_redirection_script() . '?post-redirect-to-method=1'; 650 773 651 774 $res = $this->wp_remote_post( add_query_arg( 'response_code', $response_code, $url ), array( 'timeout' => 30 ) ); … … 696 819 */ 697 820 public function test_ip_url_with_host_header() { 698 $parts = wp_parse_url( $this-> redirection_script);821 $parts = wp_parse_url( $this->get_redirection_script() ); 699 822 $this->assertIsArray( $parts ); 700 823 $this->assertNotEmpty( $parts['host'] ); … … 742 865 743 866 /** 744 * Test HTTP requests where SSL verification is disabled but the CA bundle is still populated. 867 * Test HTTP requests where SSL verification is disabled. 868 * 869 * Asserts that sslcertificates stays set when sslverify is false (#33978 / 870 * r34639), and that WP_Http::request() maps that to Requests verify / 871 * verifyname. Stops before connecting. 745 872 * 746 873 * @ticket 33978 874 * @ticket 63914 747 875 * 748 876 * @covers ::wp_remote_head 749 877 */ 750 878 public function test_https_url_without_ssl_verification() { 751 $url = 'https://wordpress.org/'; 752 $args = array( 753 'sslverify' => false, 754 ); 755 879 remove_filter( 'pre_http_request', array( $this, 'block_external_http_request' ), PHP_INT_MAX ); 756 880 add_filter( 'http_request_args', array( $this, 'filter_http_request_args' ) ); 757 758 $res = $this->wp_remote_head( $url, $args ); 759 760 remove_filter( 'http_request_args', array( $this, 'filter_http_request_args' ) ); 761 881 add_action( 'requests-requests.before_request', array( $this, 'capture_requests_options' ), 10, 5 ); 882 883 try { 884 // Call the global directly: the intentional WP_Error from the capture 885 // callback must not go through retry_on_error()'s 5s sleeps. 886 $res = wp_remote_head( 'https://wordpress.org/', array( 'sslverify' => false ) ); 887 } finally { 888 remove_filter( 'http_request_args', array( $this, 'filter_http_request_args' ) ); 889 remove_action( 'requests-requests.before_request', array( $this, 'capture_requests_options' ), 10 ); 890 } 891 892 $this->assertWPError( $res ); 762 893 $this->assertNotEmpty( $this->http_request_args['sslcertificates'] ); 763 $this->assertNotWPError( $res ); 764 } 765 766 /** 767 * Test HTTP Cookie handling. 768 * 769 * Uses the local redirection fixture when available so cookie acceptance and 770 * rejection checks do not depend on a live api.wordpress.org request. 771 * 772 * Parent-domain cookie acceptance is covered by 773 * test_parent_domain_cookie_is_sent_on_redirect(). 774 * 775 * @ticket 21182 776 * @ticket 63914 777 * 778 * @covers ::wp_remote_get 779 * @covers ::wp_remote_retrieve_body 780 */ 781 public function test_cookie_handling() { 782 $url = $this->redirection_script . '?cookie-test=1'; 783 784 $res = $this->wp_remote_get( $url ); 785 786 $this->assertNotWPError( $res ); 787 $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) ); 788 } 789 790 /** 791 * Verifies parent-domain cookies are accepted and sent on redirect. 792 * 793 * Complements test_cookie_handling(): the IP-based local fixture intentionally 794 * omits parent-domain cookies, so this named-origin mock keeps Domain=.example.test 795 * acceptance deterministic without a live network request. 796 * 797 * @ticket 21182 798 * @ticket 63914 799 * 800 * @covers ::wp_remote_get 801 * @covers WP_Http::normalize_cookies 802 */ 803 public function test_parent_domain_cookie_is_sent_on_redirect() { 804 add_action( 'requests-requests.before_request', array( $this, 'inject_parent_domain_cookie_test_transport' ), 10, 5 ); 805 806 try { 807 $res = $this->wp_remote_get( 'http://api.example.test/cookie-wildcard-test' ); 808 } finally { 809 remove_action( 'requests-requests.before_request', array( $this, 'inject_parent_domain_cookie_test_transport' ), 10 ); 810 } 811 812 $this->assertNotWPError( $res ); 813 $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) ); 814 } 815 816 /** 817 * Injects the parent-domain cookie test transport into Requests options. 894 $this->assertFalse( $this->requests_options['verify'] ); 895 $this->assertFalse( $this->requests_options['verifyname'] ); 896 } 897 898 /** 899 * Stores HTTP request args for later assertion. 900 * 901 * @param array $args Request arguments. 902 * @return array Unmodified request arguments. 903 */ 904 public function filter_http_request_args( array $args ) { 905 $this->http_request_args = $args; 906 return $args; 907 } 908 909 /** 910 * Captures Requests options and stops before a network connection. 911 * 912 * @throws WpOrg\Requests\Exception Always, after capturing options. 818 913 * 819 914 * @param string $url Request URL. … … 823 918 * @param array $options Request options (passed by reference). 824 919 */ 920 public function capture_requests_options( $url, $headers, $data, $type, &$options ) { 921 $this->requests_options = $options; 922 923 throw new WpOrg\Requests\Exception( 'Stopped after capturing the request options.', 'test_stopped' ); 924 } 925 926 /** 927 * Test HTTP Cookie handling. 928 * 929 * Uses the local redirection fixture when available so cookie acceptance and 930 * rejection checks do not depend on a live api.wordpress.org request. 931 * 932 * Parent-domain cookie acceptance is covered by 933 * test_parent_domain_cookie_is_sent_on_redirect(). 934 * 935 * @ticket 21182 936 * @ticket 63914 937 * 938 * @covers ::wp_remote_get 939 * @covers ::wp_remote_retrieve_body 940 */ 941 public function test_cookie_handling() { 942 $url = $this->get_redirection_script() . '?cookie-test=1'; 943 944 $res = $this->wp_remote_get( $url ); 945 946 $this->assertNotWPError( $res ); 947 $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) ); 948 } 949 950 /** 951 * Verifies parent-domain cookies are accepted and sent on redirect. 952 * 953 * Complements test_cookie_handling(): the IP-based local fixture intentionally 954 * omits parent-domain cookies, so this named-origin mock keeps Domain=.example.test 955 * acceptance deterministic without a live network request. 956 * 957 * @ticket 21182 958 * @ticket 63914 959 * 960 * @covers ::wp_remote_get 961 * @covers WP_Http::normalize_cookies 962 */ 963 public function test_parent_domain_cookie_is_sent_on_redirect() { 964 // Allow the canned Requests transport to run outside external-http. 965 remove_filter( 'pre_http_request', array( $this, 'block_external_http_request' ), PHP_INT_MAX ); 966 add_action( 'requests-requests.before_request', array( $this, 'inject_parent_domain_cookie_test_transport' ), 10, 5 ); 967 968 try { 969 $res = $this->wp_remote_get( 'http://api.example.test/cookie-wildcard-test' ); 970 } finally { 971 remove_action( 'requests-requests.before_request', array( $this, 'inject_parent_domain_cookie_test_transport' ), 10 ); 972 } 973 974 $this->assertNotWPError( $res ); 975 $this->assertSame( 'PASS', wp_remote_retrieve_body( $res ) ); 976 } 977 978 /** 979 * Injects the parent-domain cookie test transport into Requests options. 980 * 981 * @param string $url Request URL. 982 * @param array $headers Request headers. 983 * @param string|array $data Request data. 984 * @param string $type HTTP method. 985 * @param array $options Request options (passed by reference). 986 */ 825 987 public function inject_parent_domain_cookie_test_transport( $url, $headers, $data, $type, &$options ) { 826 988 $options['transport'] = new WP_HTTP_Parent_Domain_Cookie_Test_Transport(); … … 828 990 829 991 /** 830 * Test if HTTPS support works. 992 * Test if HTTPS support works against a live endpoint. 993 * 994 * Remains in external-http: this is intentional live TLS smoke coverage for 995 * the real transport. Parsing and arg-shape checks live elsewhere offline. 831 996 * 832 997 * @group ssl 998 * @group external-http 833 999 * @ticket 25007 1000 * @ticket 63914 834 1001 * 835 1002 * @covers ::wp_remote_get … … 851 1018 */ 852 1019 public function test_url_with_double_slashes_path() { 853 $url = $this-> redirection_script. '?rt=' . 0;1020 $url = $this->get_redirection_script() . '?rt=' . 0; 854 1021 855 1022 $path = parse_url( $url, PHP_URL_PATH ); -
trunk/tests/phpunit/tests/http/curl.php
r64265 r65320 5 5 /** 6 6 * @group http 7 * @group external-http 7 * 8 * @ticket 63914 8 9 */ 9 10 class Tests_HTTP_curl extends WP_HTTP_UnitTestCase {
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)