From 16915638725b16d45eb2b69e98ccc6e7d329941e Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Thu, 22 Oct 2015 00:07:36 +0000 Subject: [PATCH] Force the REST API URL to use `https` for its scheme when the current request is served over HTTPS and the host name matches that of the REST API URL. This allows sites to use an admin area over HTTPS with the front end over HTTP, and not end up with a cross-protocol problem when using the REST API URL in the admin area. Fixes #34299 git-svn-id: https://develop.svn.wordpress.org/trunk@35351 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/rest-api/rest-functions.php | 7 +++ tests/phpunit/tests/rest-api.php | 50 +++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/wp-includes/rest-api/rest-functions.php b/src/wp-includes/rest-api/rest-functions.php index 947efce90e..c3f6be0d43 100644 --- a/src/wp-includes/rest-api/rest-functions.php +++ b/src/wp-includes/rest-api/rest-functions.php @@ -254,6 +254,13 @@ function get_rest_url( $blog_id = null, $path = '/', $scheme = 'rest' ) { $url = add_query_arg( 'rest_route', $path, $url ); } + if ( is_ssl() ) { + // If the current host is the same as the REST URL host, force the REST URL scheme to HTTPS + if ( $_SERVER['SERVER_NAME'] === parse_url( get_home_url( $blog_id ), PHP_URL_HOST ) ) { + $url = set_url_scheme( $url, 'https' ); + } + } + /** * Filter the REST URL. * diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 8ea029ca3b..ff7e5cd56f 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -253,5 +253,55 @@ class Tests_REST_API extends WP_UnitTestCase { $this->assertEquals( 'http://' . WP_TESTS_DOMAIN . '/?rest_route=/', get_rest_url() ); } + /** + * @ticket 34299 + */ + public function test_rest_url_scheme() { + if ( isset( $_SERVER['HTTPS'] ) ) { + $_https = $_SERVER['HTTPS']; + } + $_name = $_SERVER['SERVER_NAME']; + $_SERVER['SERVER_NAME'] = parse_url( home_url(), PHP_URL_HOST ); + $_siteurl = get_option( 'siteurl' ); + + set_current_screen( 'edit.php' ); + $this->assertTrue( is_admin() ); + + // Test an HTTP URL + unset( $_SERVER['HTTPS'] ); + $url = get_rest_url(); + $this->assertSame( 'http', parse_url( $url, PHP_URL_SCHEME ) ); + + // Test an HTTPS URL + $_SERVER['HTTPS'] = 'on'; + $url = get_rest_url(); + $this->assertSame( 'https', parse_url( $url, PHP_URL_SCHEME ) ); + + // Switch to an admin request on a different domain name + $_SERVER['SERVER_NAME'] = 'admin.example.org'; + update_option( 'siteurl', 'http://admin.example.org' ); + $this->assertNotEquals( $_SERVER['SERVER_NAME'], parse_url( home_url(), PHP_URL_HOST ) ); + + // // Test an HTTP URL + unset( $_SERVER['HTTPS'] ); + $url = get_rest_url(); + $this->assertSame( 'http', parse_url( $url, PHP_URL_SCHEME ) ); + + // // Test an HTTPS URL + $_SERVER['HTTPS'] = 'on'; + $url = get_rest_url(); + $this->assertSame( 'http', parse_url( $url, PHP_URL_SCHEME ) ); + + // Reset + if ( isset( $_https ) ) { + $_SERVER['HTTPS'] = $_https; + } else { + unset( $_SERVER['HTTPS'] ); + } + $_SERVER['SERVER_NAME'] = $_name; + update_option( 'siteurl', $_siteurl ); + set_current_screen( 'front' ); + + } }