Make WordPress Core

Opened 9 years ago

Last modified 6 months ago

#35561 new defect (bug)

function wp_admin_canonical_url() not using configured site url when constructing canonical url link tag

Reported by: ilude's profile ilude Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.4.1
Component: Administration Keywords: reporter-feedback dev-feedback has-patch
Focuses: administration Cc:

Description (last modified by johnbillion)

I was having an issue with the wp_admin_canonical_url() function in wp-admin/includes/misc.php and I have a suggested fix

I am running word press behind a reverse nginx proxy on a different box so my main site is at http://www.rammount.com and the blog is at http://www.rammount.com/blog

The blog url is set in the WordPress configuration. But when you log into the admin section the wp_admin_canonical_url() function does not pick up the configured url instead it constructs the url without the /blog. This of course breaks links in the admin section, constantly redirecting things to http://www.rammount.com without the /blog

by changing the following line:
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

to:
$current_url = set_url_scheme(home_url(add_query_arg(array(),$wp->request)) . $_SERVER['REQUEST_URI']);

the problem is solved. the proper url is created and as such the links in the admin section that use the canonical url link function correctly.

Hoping to have this change evaluated for inclusion, so that I don't have to remake this edit every time one of my designers updates the WordPress installation?

Attachments (1)

35561.diff (1.7 KB) - added by hallman76 8 years ago.

Download all attachments as: .zip

Change History (16)

#1 @johnbillion
9 years ago

  • Description modified (diff)
  • Keywords reporter-feedback added

Thanks for the ticket @ilude.

This sounds like it might be a problem with your reverse proxy configuration whereby the full URL path is not being passed through from Nginx.

Can you let us know what the value of $_SERVER['REQUEST_URI'] is when accessing your blog's admin area? If it's empty, or doesn't contain the /blog prefix, then this is an issue with the your reverse proxy implementation (possibly a missing fastcgi_param setting).

#2 @ilude
9 years ago

If the reverse proxy setup was incorrect the non administration sections of the site would not function. Those sections are not relying on the $_SERVER['REQUEST_URI'] var to contain the /blog prefix in the url. They correctly use the SITE_URL setting to create their links.

The admin section is not behaving the same way, it is ignoring the SITE_URL setting and trying to generate the canonical url using request parameters. What I'm trying to explain is that the admin section is generating the canonical url differently than the non admin sections of the site. If I adjust my configuration the way you suggest the non admin sections will generate incorrect urls.

The issue is not a proxy configuration issue, it is the inconsistent url generation differences between the non admin and admin sections of the site.

The rel_canonical() function that the non admin sections rely on uses get_permalink() function that in turn relies the home_url() function. This is why I suggested using that as the fix, so that the admin section behaved the same as the non admin section when generating urls.

Now perhaps I'm missing something important, because I'm not a wordpress developer, with relying on home_url() in the admin section, but regardless the behavior needs to be consistent.

Providing consistent behavior would also make plugins like this unneeded as well http://chooseplugin.com/plugin-info/remove-wp-canonical-url-admin-hack/

Last edited 9 years ago by ilude (previous) (diff)

#3 @dd32
9 years ago

@ilude Regardless of how it's supposed to work (or other parts of the code work) if you can provide the actual values of the variables in a scenario like the one you describe, it's possible for others to duplicate the behaviour you're seeing.

At first glance at the ticket, @johnbillion's description sounds correct, it feels like your reverse proxy setup isn't passing the requested URL through properly, or that it's being eaten by the server somewhere. without seeing the actual values though, we can't verify it either way.

#4 @riyazmuhammad
8 years ago

I have the same issue of @ilude . My website admin part shows an error:
Uncaught SecurityError: Failed to execute 'replaceState' on 'History': A history state object with URL 'blog.example.com/wp-admin/index.php'; cannot be created in a document with origin 'example.com'; and URL 'example.com/blog/wp-admin/index.php';

When I dig more in to the console error, found the line causing error is:
window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );

URL loses its /blog part when I try to save any settings in admin area( eg: settings > genaral ).
Is there any solution for this?

@hallman76
8 years ago

#5 @hallman76
8 years ago

sorry - ignore that attached patch. Needs more testing!

Last edited 8 years ago by hallman76 (previous) (diff)

#6 @higuita
8 years ago

I also had this problem and IMHO, wp-admin-canonical is broken as it assumes only one way of working.

In my setup, i have a main site and want to add a subdirectory blog to the site:

main site: www.example.com
blog: www.example.com/blog

we are using wpengine as a blog backend, so i configured the site url and wordpress url to https://www.example.com/blog and setup the main site to do a reverse proxy to the blog:

  location ^~ /blog {
      proxy_set_header HOST $host;
      proxy_set_header Proxy "";
      proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      # notice the ending /, so the /blog is converted to / in the backend
      proxy_pass https://wpengine/ ;
  }

I can not change the wpengine config so that is accepts /blog/ requests directly, i have to
convert then to / for it to work.

With this the public wordpress works fine, but the wp-admin tried to access https://www.example.com/wp-admin instead of https://www.example.com/blog/wp-admin. This is only because of wp-admin-canonical, removing that, all works fine.

$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

Here we we can see that wordpress is assuming that what it gets is the final URL, that might not be the true. Not all people can control the wordpress install and may prefer to manage this in the reverse proxy. Think in wordpress hosting, or docker images that work both in / and /folder setups, without any special change other than the site and home url.

wp-admin-canonical must not assume how the site works, it should trust the site or wordpress url and let the reverse proxy take care of the rest.

The simple fact that this plugin exists proves that wordpress is wrongly assuming how everything should work. There are many setups out there, not all work the same.

Pleas change this or give a simple way to disable it. The plugin is a workaround, but only after people got this error and lost several hours trying to figure why this is not working

#7 @techwebliu
8 years ago

We came by this problem too.

#8 @georf
7 years ago

I searched the hours because of this problem. I have the nearly the same setup like @higuita and the frontend works perfectly. In the backend the wrong wp-admin-canonical url breaks the links.

Could you please repair this url to safe live time?

#9 @danychen
4 years ago

  • Keywords dev-feedback added

I have this problem too, the thing is that if you use reverse proxy, you got let the REQUEST_URI contain the prefix for admin to work. which makes deploy a bit inconvenient, mostly you cloud add an addition dir for the path to be correct.

In nginx you can do:

location /blog {
  alias /Users/dany/Projects/blog;
  try_files $uri $uri/ /index.php$is_args$args;
  location ~* "\.php$" {
    fastcgi_pass   unix:/Users/dany/.phpbrew/php/php-7.0.33/var/run/php-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $request_filename;
    include        fastcgi_params;
  }
}

which makes you REQUEST_URI to be the full url, but the actual script is not in blog dir.

In docker it's a bit easier to just include additional path for the prefix, such as -v ./src:/var/www/html/blog

you can control it to work, but if you don't have control over the blog, then reverse proxy just don't work on admin unless use some sort of way the manipulate the REQUEST_URI.

Conclusion:

I think the Point is that why admin and front end have different behavior for how url is constructed, we can make configs that make it to work provided that we have control over the wordpress deployment.

This ticket was mentioned in PR #1504 on WordPress/wordpress-develop by jefferyto.


4 years ago
#10

  • Keywords has-patch added

Currently, wp_admin_canonical_url() uses $_SERVER['HTTP_HOST'] to build an admin page's canonical URL. This URL will point to an incorrect host if $_SERVER['HTTP_HOST'] does not match the site URL host, e.g. when Wordpress is used behind a reverse proxy.

This uses admin_url() so that the canonical URL will take the configured site URL into account.

Trac ticket: https://core.trac.wordpress.org/ticket/35561

#11 @jefferyto
4 years ago

As mentioned by the GitHub bot, I have a PR (https://github.com/WordPress/wordpress-develop/pull/1504) that addresses this issue - would appreciate it if a core committer can take a look. (This is essentially the same fix as for #36201.)

hanspoo commented on PR #1504:


3 years ago
#12

Please merge this code, the problem is critical for running wordpress under a prefix / context.

#13 @prionkor
16 months ago

I have added a PR for a filter, it should be helpful for anyone who wants to make change to canonical url.

https://github.com/WordPress/wordpress-develop/pull/5412

Trac ticket #59545

Last edited 16 months ago by prionkor (previous) (diff)

#14 @jefferyto
10 months ago

For those using WordPress 6.5 or newer, adding something like this to your theme should work around this issue:

<?php
function trac35561_wp_admin_canonical_url( $filtered_url ) {
        $removable_query_args = wp_removable_query_args();

        if ( ! empty( $removable_query_args ) ) {
                $current_url  = admin_url( preg_replace( '#^[^?]*/wp-admin/#i', '', $_SERVER['REQUEST_URI'] ) );
                $filtered_url = remove_query_arg( $removable_query_args, $current_url );
        }

        return $filtered_url;
}
add_filter( 'wp_admin_canonical_url', 'trac35561_wp_admin_canonical_url' );

If this works for you, please leave a comment on this ticket so that the developers will know this issue continues to exist.

p4block commented on PR #1504:


6 months ago
#15

The patch that was eventually merged doesn't solve this problem, it's currently near-impossible to host Wordpress behind a reverse proxy that removes the subpath from the request before forwarding it to the container.
The main site works, the admin panel is the only one returning broken URLs

This fix is basically required for a k8s+wordpress setup. Some people do a filesystem symlink and don't take away the subpath at the ingress, but that hack has various real world problems once you start getting involved with it, and it's a hack anyway.

Note: See TracTickets for help on using tickets.