WordPress.org

Make WordPress Core

Opened 9 months ago

Closed 2 months ago

#48439 closed defect (bug) (duplicate)

Wrong configuration parameter is taken as Rest Api root

Reported by: dlavrenuek Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.4
Component: REST API Keywords: has-patch
Focuses: rest-api Cc:

Description

Result of the bug: No updates can be made to the content in the backend

There is a configuration for siteurl and home in the WordPress backend. While siteurl is the WordPress instance home can be another domain that is used for the frontend. While logged into the backend The wpApiSettings js variable is filled with the value from home instead of siteurl. This breaks the backend making it impossible to create or save any content if the domain used for the actual frontend is configured to only proxy get requests.

Example site configuration:
The WordPress instance is on https://some.domain = siteurl
The Frontend is on https://some-other.domain = home
some-other.domain is configured to only proxy get requests.
While logged in to the backend the wpApiSettings is filled with "https://some-other.domain" instead of "https://some.domain"

The problem lies in the function get_rest_url in includes/rest-api.php that builds the wrong url. A patch is provided:

Index: wp-includes/rest-api.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- wp-includes/rest-api.php	(date 1572118458000)
+++ wp-includes/rest-api.php	(date 1572118458000)
@@ -356,14 +356,14 @@
 		global $wp_rewrite;
 
 		if ( $wp_rewrite->using_index_permalinks() ) {
-			$url = get_home_url( $blog_id, $wp_rewrite->index . '/' . rest_get_url_prefix(), $scheme );
+			$url = get_site_url( $blog_id, $wp_rewrite->index . '/' . rest_get_url_prefix(), $scheme );
 		} else {
-			$url = get_home_url( $blog_id, rest_get_url_prefix(), $scheme );
+			$url = get_site_url( $blog_id, rest_get_url_prefix(), $scheme );
 		}
 
 		$url .= $path;
 	} else {
-		$url = trailingslashit( get_home_url( $blog_id, '', $scheme ) );
+		$url = trailingslashit( get_site_url( $blog_id, '', $scheme ) );
 		// nginx only allows HTTP/1.0 methods when redirecting from / to /index.php
 		// To work around this, we manually add index.php to the URL, avoiding the redirect.
 		if ( 'index.php' !== substr( $url, 9 ) ) {
@@ -375,7 +375,7 @@
 
 	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 ) ) {
+		if ( $_SERVER['SERVER_NAME'] === parse_url( get_site_url( $blog_id ), PHP_URL_HOST ) ) {
 			$url = set_url_scheme( $url, 'https' );
 		}
 	}

Attachments (1)

rest-api.patch (1.5 KB) - added by dlavrenuek 9 months ago.
patch

Download all attachments as: .zip

Change History (5)

@dlavrenuek
9 months ago

patch

#1 @TimothyBlynJacobs
9 months ago

  • Focuses administration removed
  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed
  • Version changed from 5.2.4 to 4.4

Hello @dlavrenuek!

This is actually intentional behavior. If you need to change this, you can use the rest_url filter in get_rest_url.

See #42869, #46246

#2 @dlavrenuek
9 months ago

Hi @TimothyBlynJacobs,

thanks for the quick reply. The only intention I can find in the other tickets is this one: https://core.trac.wordpress.org/ticket/37020#comment:1

some endpoint data is publicly discoverable so the public facing url (aka home_url) is a better fit

If this is the case then it looks like a design flaw because "some" public requests should not break the backend functionality even if there is a workaround.

#3 @tbclark3
2 months ago

  • Resolution duplicate deleted
  • Status changed from closed to reopened

I have discovered a different complication of the same issue. I am running WordPress instances under Docker with reverse proxy provided by Apache. The Docker instance is listening only on port 80; Apache is listening on 443. If rest_url chooses https (which it does by default in my context) then editing works from the browser; however, all rest api requests from plugins fail because they are trying to get to https on the Docker instance, which doesn't exist. Forcing rest_url to use http fixes the rest requests from plugins, but breaks the browser since browsers don't allow mixed content. Setting the "Wordpress address" field to http and the "Site address" field should logically fix the problem, but it doesn't. There should be a way to differentiate between rest_url requests that come internally from plugins (using http) vs those that are intended to be used from the browser (using https).

#4 @TimothyBlynJacobs
2 months ago

  • Resolution set to duplicate
  • Status changed from reopened to closed

Duplicate of #42869.

@tbclark3 I would open a separate ticket for that. I think you'd have that problem any time WordPress core or a plugin attempts to make a loopback request.

It should also be noted that in most cases "internal" rest requests should be done using rest_do_request which doesn't perform an actual HTTP request.

Note: See TracTickets for help on using tickets.