Make WordPress Core

Opened 13 years ago

Closed 13 years ago

Last modified 20 months ago

#17048 closed feature request (maybelater)

URLs delivered to the browser should be root-relative

Reported by: dmole's profile dmole Owned by: edwardw's profile edwardw
Milestone: Priority: normal
Severity: normal Version: 3.1
Component: General Keywords: close
Focuses: Cc:

Description

Using absolute URLs are needed for email, and maybe RSS, and RPC.

For normal pages on a fresh install (default theme):

-Using absolute URLs like "http://domain.tld/path/file" (current behavior) breaks css and links if the server uses more then one domain/ip

-Using relative URLs like "../path/file" would likely break a lot and make WordPress unnecessarily complicated.

-Using root-relative URLs like "/path/file" is the correct design decision maximizing compatibility/functionality.

Attachments (1)

patch17048_draft.diff (20.7 KB) - added by edwardw 13 years ago.
Proof-of-concept draft patch for root-relative URLs (not final)

Download all attachments as: .zip

Change History (68)

#2 @nacin
13 years ago

Root-relative URLs aren't really proper. /path/ might not be WordPress, it might be outside of the install. So really it's not much different than an absolute URL.

Any relative URLs also make it significantly more difficult to perform transformations when the install is moved. The find-replace is going to be necessary in most situations, and having an absolute URL is ironically more portable for those reasons.

As you said, absolute URLs are needed in numerous other places. Needing to add these in conditionally will add to processing, as well as introduce potential bugs (and incompatibilities with plugins).

Unfortunately, the opinion of those threads are skewed in the direction you mention due to most of them not really understanding the problem or the design decision (nor are most of them active core contributors or core developers). I've tried to cover a bit of the design decision on wp-hackers before, and I've been able to locate this reply of mine (the first part, in particular):

http://lists.automattic.com/pipermail/wp-hackers/2010-November/036195.html

#3 @dmole
13 years ago

Addressing Nacin's concerns:

Root-relative URLs aren't really proper. /path/ might not be WordPress, it might be outside >of the install. So really it's not much different than an absolute URL.

WordPress already requires you to provide the /path/to/wordpress, the difference in omitting the protocal://domain.tld is that WordPress will work simultaneously with different domains/IPs and protocols(http/https) out of the box. (yes there is already an ugly https rewrite and it breaks with caching plugins)

Any relative URLs also make it significantly more difficult to perform transformations when >the install is moved. The find-replace is going to be necessary in most situations, and >having an absolute URL is ironically more portable for those reasons.

All URLs in the DB should be relative to the WordPress root requiring no changes on migration.

As you said, absolute URLs are needed in numerous other places. Needing to add these in >conditionally will add to processing, as well as introduce potential bugs (and >incompatibilities with plugins).

It will actually reduce processing because it will remove the https hack for relative urls. additionally we would just call a different function for root-relative URLs avoiding the processing hit of an if statement. Bugs and incompatibilities should be minimal if plugins were written in a robust way, but yes they happen with every change to WordPress.

Unfortunately, the opinion of those threads are skewed in the direction you mention due to >most of them not really understanding the problem or the design decision (nor are most of >them active core contributors or core developers). I've tried to cover a bit of the design >decision on wp-hackers before, and I've been able to locate this reply of mine (the first >part, in particular):

I agree the lack of knowledge is a problem, I think it would be great if there were a website for commonly disputed design decisions. It would save us all a lot of time.

http://lists.automattic.com/pipermail/wp-hackers/2010-November/036195.html:

In the red corner, WordPress should store relative URLs. Relative to what,
I'm not sure, as WordPress is often in a subdirectory, which means we'll
always need to process the content to then add in the rest of the path. This
introduces overhead.

Relative to the WordPress root defined in the UI. The overhead is already there and it will likely shrink not grow. (currently we check for https and root folder)

Keep in mind that there are two types of relative URLs, with and without the
leading slash. Both have caveats that make this impossible to properly
implement.

As Peter points out, I'm not even sure how we'd detect URLs we need to now
append to. A placeholder perhaps? What better placeholder than the domain
itself? Were there to be this implemented, it would actually decrease
portability of your content, as your content must now go through a
non-agnostic filter to actually be useful.

There is no need for a placeholder you just strip all the domains off on upgrade.

You can't sacrifice stability for perceived portability. Read that back.

I can't call a fresh install with no CSS when NATed or used with another domain "stable"

In the blue corner, WordPress should (and does) store absolute URLs. This
requires no pre-processing of content, no overhead, no ambiguity. If you
need to relocate, it is a global find-replace in the database.

you actually currently pre-process https and the WordPress root folder, so there would be no performance hit.

Really, what you should do, is reverse the deployment process, as Otto
suggests. Don't work off http://localhost/example/ then try to deploy to
example.com. Rather, have your install believe it is the live example.com,
then fake it to work on your staging environment. If it breaks on live, you
have a problem; it it breaks on staging, well, that's not much of a problem,
is it?

The problem is if you have 1 live environment with >1 domain/IP/protocol

...

Please provide a specific example if I have missed anything. I agree it will be work to implement root-relative URLs, but I also believe WordPress will be a more robust product as a result. Thanks for your comment.

#4 @solarissmoke
13 years ago

  • Cc solaris.smoke@… added

#5 @Tandem
13 years ago

  • Cc Tandem added

#6 @edwardw
13 years ago

  • Keywords dev-feedback added
  • Owner set to edwardw
  • Status changed from new to accepted
  • Summary changed from urls deliverd to the browser should be root-relative to URLs delivered to the browser should be root-relative

I would have to agree here. Many other pieces of PHP or ASP.NET software run fine when the domain name is different from what the application is installed to - the issue here is that it is the same server but just using multiple interfaces (IP addresses, NAT gateways, reverse proxies, and so forth). For example, if I have my development test WP server running at http://localhost/ with IP 192.168.1.1, then when I visit it on another computer with http://192.168.1.1/ all the links are absolute to http://localhost/, resulting in things like http://localhost/wordpress/?feed=rss2 that don't resolve on the other computer. This means all images, links and CSS are completely broken. In addition, many networks involve reverse proxies and NAT gateways (e.g. outside may see http://blog.example.com/ but employee sees http://wordpress.servers.example.com/ or something like that).

I think that this feature would make WordPress a more robust and tolerant software. If there is no significant opposition I will start working on a solution to this problem.

Last edited 13 years ago by edwardw (previous) (diff)

#7 follow-up: @nacin
13 years ago

# wp-config.php
ob_start( 's_localhost_192' );
function s_localhost_192( $string ) {
     return str_replace( 'http://localhost/', 'http://192.168.1.1/', $string );
}

#8 @nacin
13 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from accepted to closed
Last edited 13 years ago by nacin (previous) (diff)

#9 @edwardw
13 years ago

  • Resolution wontfix deleted
  • Status changed from closed to reopened

And other domains? What if the same server is available under multiple domains (IP, internal domain, external domain)? Why do you so significantly oppose the proposal for root-relative URLs?

Though I suppose I could modify what you put above to pull the user's visiting host from the $_SERVER['HTTP_HOST'] variable, it would be just easier to amend WordPress serve root-relative URLs?

Last edited 13 years ago by edwardw (previous) (diff)

#10 @nacin
13 years ago

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

I didn't intend to close this ticket -- I had searched for my comment (that turns out to be above), opened the ticket in a new window, and referenced the ticket above. I didn't realize they were the same ticket until I posted. Yeah, been a long day.

That said, this is a deliberate design decision. We don't have any plans to change this.

#11 in reply to: ↑ 7 ; follow-up: @dmole
13 years ago

Replying to nacin:

Thanks for the config hint, I found this code works:

#wp-config.php:

 /** Hack to make URLs root relative */
 ob_start( 'make_url_root_relative' );
 function make_url_root_relative( $string ) {
      return  preg_replace( '/https?...[^\/]+\//i', '/', $string );
 }

It's more run time work when a proper patch would actually be less, but those who care will be using compressed caching anyway.

It would be best if this did not effect URLs used in emails. Maybe someone will comment on that.

#12 in reply to: ↑ 11 ; follow-up: @dmole
13 years ago

Replying to dmole:
Realizing ob_start is a PHP function that rewrites the whole page, that is not a usable solution for anyone who wants external links. (unless they use a preset list of known domains in the callback function)

 /** Hack to make URLs root relative */
 ob_start( 'make_url_root_relative' );
 function make_url_root_relative( $string ) {
      return  preg_replace( '/https?...(myblog.com|127.0.0.1|nat.whatever.tld)\//i', '/', $string );
 }

I'm guessing the function should check if it's output is an email, ideas?

#13 in reply to: ↑ 12 ; follow-up: @edwardw
13 years ago

Replying to dmole:

Replying to dmole:
Realizing ob_start is a PHP function that rewrites the whole page, that is not a usable solution for anyone who wants external links. (unless they use a preset list of known domains in the callback function)

 /** Hack to make URLs root relative */
 ob_start( 'make_url_root_relative' );
 function make_url_root_relative( $string ) {
      return  preg_replace( '/https?...(myblog.com|127.0.0.1|nat.whatever.tld)\//i', '/', $string );
 }

I'm guessing the function should check if it's output is an email, ideas?

What's wrong with replacing with whatever domain the user is on ($_SERVER['HTTP_HOST'])? With this method, you don't need to maintain a list of known network interfaces, since if the browser can access it, it must be accessible on that interface.

Last edited 13 years ago by edwardw (previous) (diff)

#14 in reply to: ↑ 13 @dmole
13 years ago

Replying to edwardw:

What's wrong with replacing with whatever domain the user is on ($_SERVER['HTTP_HOST'])? With this method, you don't need to maintain a list of known network interfaces, since if the browser can access it, it must be accessible on that interface.

I don't think you properly understood the problem, (there are reasons why URLS are not dynamic everywhere).

A) Replacing link prefixes with $_SERVERHTTP_HOST? in ob_start really makes no difference because the browser will do it anyway, If there are any features that run in the background(from the fs not using a network) it might become meaningless, If an email is triggered from a local network non-local users will get useless links.

B) Replacing $_SERVERHTTP_HOST? with "" in ob_start will not work because the links are not made with $_SERVERHTTP_HOST? they are made with some arbitrary DB or user controlled value.

If you are suggesting something else please provide an example patch like nacin did to clearly test and convey your meaning.

with more testing it becomes clear that the ob_start options are unusable because it misses headers like those used in redirects to wp-login.php, and it gets urls it should not like the "siteurl" setting itself.

IMO the only reason reason this is not implemented is that it would be a big-ish patch, someone was planning to implement this when they made the "siteurl" setting separate from the "home" setting, because there is no other good reason to separate them.

#15 follow-up: @edwardw
13 years ago

So what you are saying is that with ob_start you would break links to other posts in the post content and things like that as opposed to the dynamically generated part. What we do need is absolute URLs for RSS feeds, e-mail notifications and external non-browser URLs. For URLs served to the browser, then what we need is to serve URLs relative to the root specified in the database, with external URLs (email, RSS) served the "external" domain.

Also, I see what you mean when you say that it might break e-mails if URLs are generated internally, since the domain that the insider sees is different from the outsider.

Then why do you oppose me trying to find a solution to this problem? I think it would make WordPress more robust as a result, but I keep running into un-cooperative responses.

Last edited 13 years ago by edwardw (previous) (diff)

#16 in reply to: ↑ 15 ; follow-up: @dmole
13 years ago

Replying to edwardw:

So what you are saying is that with ob_start you would break links to other posts in the post content and things like that as opposed to the dynamically generated part. What we do need is absolute URLs for RSS feeds, e-mail notifications and external non-browser URLs. For URLs served to the browser, then what we need is to serve URLs relative to the root specified in the database, with external URLs (email, RSS) served the "external" domain.

Also, I see what you mean when you say that it might break e-mails if URLs are generated internally, since the domain that the insider sees is different from the outsider.

yes that's the idea

Then why do you oppose me trying to find a solution to this problem? I think it would make WordPress more robust as a result, but I keep running into un-cooperative responses.

It would be great if you could make a solution, I was just pointing out that your previous comment was on the wrong track; $_SERVER['HTTP_HOST' ] won't help at all (it won't hurt either), what would help is if we could make or find a central place where URLS are prefixed with "siteurl"+"home" and make it only use "home" if the URL is sent to a browser.

@edwardw
13 years ago

Proof-of-concept draft patch for root-relative URLs (not final)

#17 in reply to: ↑ 16 @edwardw
13 years ago

  • Resolution maybelater deleted
  • Status changed from closed to reopened

Replying to dmole:

Replying to edwardw:

So what you are saying is that with ob_start you would break links to other posts in the post content and things like that as opposed to the dynamically generated part. What we do need is absolute URLs for RSS feeds, e-mail notifications and external non-browser URLs. For URLs served to the browser, then what we need is to serve URLs relative to the root specified in the database, with external URLs (email, RSS) served the "external" domain.

Also, I see what you mean when you say that it might break e-mails if URLs are generated internally, since the domain that the insider sees is different from the outsider.

yes that's the idea

Then why do you oppose me trying to find a solution to this problem? I think it would make WordPress more robust as a result, but I keep running into un-cooperative responses.

It would be great if you could make a solution, I was just pointing out that your previous comment was on the wrong track; $_SERVER['HTTP_HOST' ] won't help at all (it won't hurt either), what would help is if we could make or find a central place where URLS are prefixed with "siteurl"+"home" and make it only use "home" if the URL is sent to a browser.

Please see the sample proof-of-concept patch attached above - it is not perfect and only a first draft, but it implements the ideas from this topic and if it is on the right track then the patch can be refined and polished.

Again, just trying to help find a solution for what seems to me a good idea.

Last edited 13 years ago by edwardw (previous) (diff)

#18 @dmole
13 years ago

Thanks edwardw, at first glance that looks like it's on the right track.
Is there a reason not to merge the three functions (get_home_url get_site_url network_site_url) into one?
Also I hope the other 101 url functions call one of the three you changed
grep -R "function .*_url" * | grep -v "js:"
I'll test out your patch a bit more later

#19 @kawauso
13 years ago

Defaulting to root_relative on things like get_permalink() sounds like it'll break any existing code that expects absolute URLs.

#20 follow-up: @dmole
13 years ago

Images, links, and css seem to all be working, but redirects are not:

http://192.168.1.110/wordpress/wp-admin/

redirects to

http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2F192.168.1.110%2Fwordpress%2Fwp-admin%2F&reauth=1

so that patch still needs redirects tweaked before it's usable.
Good work so far.

#21 in reply to: ↑ 20 @edwardw
13 years ago

Replying to dmole:

Images, links, and css seem to all be working, but redirects are not:

http://192.168.1.110/wordpress/wp-admin/

redirects to

http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2F192.168.1.110%2Fwordpress%2Fwp-admin%2F&reauth=1

so that patch still needs redirects tweaked before it's usable.
Good work so far.

$ wget http://192.168.2.101:81/wordpress/wp-admin/
--2011-08-14 20:15:36--  http://192.168.2.101:81/wordpress/wp-admin/
Connecting to 192.168.2.101:81... connected.
HTTP request sent, awaiting response... 302 Found
Location: /wordpress/wp-login.php?redirect_to=http%3A%2F%2F192.168.2.101%3A81%2Fwordpress%2Fwp-admin%2F&reauth=1 [following]
--2011-08-14 20:15:37--  http://192.168.2.101:81/wordpress/wp-login.php?redirect_to=http%3A%2F%2F192.168.2.101%3A81%2Fwordpress%2Fwp-admin%2F&reauth=1
Connecting to 192.168.2.101:81... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1980 (1.9K) [text/html]
Saving to: `index.html'

100%[======================================>] 1,980       --.-K/s   in 0s      

2011-08-14 20:15:37 (111 MB/s) - `index.html' saved [1980/1980]

At least this part looks OK to me - you might want to check your siteurl and home settings in your wp_options table. The "external" URL used for feeds and such (in the database) is localhost:81.

#22 follow-up: @azaozz
13 years ago

  • Keywords close added; dev-feedback removed

I'm with @nacin on this. Having absolute URLs in WordPress is a design decision that's not likely to change. Furthermore I don't see any compelling user case that requires it to change. The user case here:

-Using absolute URLs like " http://domain.tld/path/file" (current behavior) breaks css and links if the server uses more then one domain/ip

is very rare and should preferably be handled in .htaccess or web.config as that will be the fastest solution. Don't see the need to add anything to WordPress for that.

#23 in reply to: ↑ 22 ; follow-up: @edwardw
13 years ago

  • Keywords close removed

Replying to azaozz:

I'm with @nacin on this. Having absolute URLs in WordPress is a design decision that's not likely to change. Furthermore I don't see any compelling user case that requires it to change. The user case here:

-Using absolute URLs like " http://domain.tld/path/file" (current behavior) breaks css and links if the server uses more then one domain/ip

is very rare and should preferably be handled in .htaccess or web.config as that will be the fastest solution. Don't see the need to add anything to WordPress for that.

Please see comments 3 and 6 above for the rationale that is being discussed here. Root-relative URLs will make WordPress a more robust and compatible piece of software, but those of us interested in feature development who are trying to fix it here keep bumping into uncooperative responses or are being shafted and ignored.

#24 in reply to: ↑ 23 ; follow-up: @azaozz
13 years ago

Replying to edwardw:

This ticket was marked for "dev-feedback" so I gave some feedback and suggested action. Removing the "close" keyword won't change that :)

Root-relative URLs will not make WordPress more robust or more compatible. But this is just my opinion. If you want to discuss such design decision the right place would be the wp-hackers mailing list.

#25 in reply to: ↑ 24 @edwardw
13 years ago

Replying to azaozz:

Replying to edwardw:

This ticket was marked for "dev-feedback" so I gave some feedback and suggested action. Removing the "close" keyword won't change that :)

Root-relative URLs will not make WordPress more robust or more compatible. But this is just my opinion. If you want to discuss such design decision the right place would be the wp-hackers mailing list.

Then why the systematic and purposeful discrimination and shafting of those interested in feature development? At least I have tried to produce a draft patch to prove this concept is possible. Unfortunately, people like you come and tell us that we can not and must not attempt to improve WordPress "by design". A bit of tolerance and understanding to make room for improvement would be much appreciated here.

#26 @dmole
13 years ago

edwardw you deserve respect for you work and tolerance. Hopefully, like all the others in this thread, azaozz will come to respectfully attempt to address this bug, I'm sure he was just to busy to properly take the time to understand and address this bug.

Replying to edwardw:
Hi edwardw, you only used wget with one domain/ip so that's not really a test of of your good work :) this is what I get:

wget http://127.0.0.1/wordpress/wp-admin/ -O /dev/null
--2011-08-16 12:27:03--  http://127.0.0.1/wordpress/wp-admin/
Connecting to 127.0.0.1:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2F127.0.0.1%2Fwordpress%2Fwp-admin%2F&reauth=1 [following]
--2011-08-16 12:27:05--  http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2F127.0.0.1%2Fwordpress%2Fwp-admin%2F&reauth=1
Resolving my.domain.tld... 55.155.155.155
Connecting to my.domain.tld|55.155.155.155|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1943 (1.9K) [text/html]
Saving to: `/dev/null'

100%[====================================================================================================================================================================================================================================>] 1,943       --.-K/s   in 0s      

2011-08-16 12:27:06 (77.3 MB/s) - `/dev/null' saved [1943/1943]

and

wget http://my.domain.tld/wordpress/wp-admin/ -O /dev/null
--2011-08-16 12:29:09--  http://my.domain.tld/wordpress/wp-admin/
Resolving my.domain.tld... 55.155.155.155
Connecting to my.domain.tld|55.155.155.155|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2Fmy.domain.tld%2Fwordpress%2Fwp-admin%2F&reauth=1 [following]
--2011-08-16 12:29:10--  http://my.domain.tld/wordpress/wp-login.php?redirect_to=http%3A%2F%2Fmy.domain.tld%2Fwordpress%2Fwp-admin%2F&reauth=1
Connecting to my.domain.tld|55.155.155.155|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1943 (1.9K) [text/html]
Saving to: `/dev/null'

100%[====================================================================================================================================================================================================================================>] 1,943       --.-K/s   in 0s      

2011-08-16 12:29:10 (101 MB/s) - `/dev/null' saved [1943/1943]

Replying to azaozz:

...I don't see any compelling user case that requires it to change. The user case ... is very rare and should preferably be handled in .htaccess or web.config...

azaozz, thanks for the input but I don't think you understand the use case because the problem can't be addressed with apache config. Additionally NAT, sub nets, multiple IPs, and multiple domains are anything but "rare". Obviously it not rare but imposable for users to use a vanilla WordPress site from with more than one domain, that is the reason for this bug report. (If I'm wrong or missing something please educate us) My opinion is that the FSM would love if people gave solid support for there "opinions".

Clarification:The objective is to make a vanilla WordPress site work from more than one URL ip/domain/port.

ps azaozz can you link us to an online log of the wp-hackers mailing list? (in case we get kicked out of here)

#27 @dmole
13 years ago

http://lists.automattic.com/pipermail/wp-hackers/
seems to be the official yet external log, I'll continue there IF we are kicked out of here or someone reasons with us to use it instead.

#28 follow-up: @dd32
13 years ago

  • Keywords close added
  • Type changed from defect (bug) to feature request

http://lists.automattic.com/pipermail/wp-hackers/ seems to be the official yet external log

Correct, That's the official (and not really external - it's just there's never been enough time and a compelling reason to set up the lists on the WordPress.org servers) location for such discussions.

I'm not going to say it's a waste of your time continueing the patch, But I will say that since it's a design choice, Commitors are not likely to want to touch this, as such, any patch is simply going to go stale. You'd be far better off implementing this as a plugin which those interested can use, which would be more likely to be future compatible (I realise that determining where the url is being used would be hard, therefor, you'd have to just do it root-relative in the locations you *knew* 100% it'd be ok).

One example for reasons a absolute url is easier, is when moving the site to another domain, You can simply replace all the site url's. With this solution, You can't reliably move it between directories, moving between hosts is fine, just as long as all paths end up the same. You'd also have to investigate Exports/Imports, as that would be affected too.

Long story short, to me, It's not a problem that needs fixing, In the sense, that there are other solutions available already which fill the needs mentioned in this ticket. the output buffering items mentioned above are one method, my favourite method is to dynamically define WP_SITEURL/WP_HOME, or filter the siteurl option, or filter the site_url()/admin_url()/includes_url()/home_url() returns to respect the current hostname, etc.. there's always a method which suits the site/environment in question.

Adding the close keyword again, to signify/track, that multiple developers have suggested it be closed, removing it doesn't change that decision. Also, It's a feature request to use root-relative links, as using absolute url's is not a bug, rather a decision.

#29 in reply to: ↑ 28 ; follow-up: @dmole
13 years ago

Replying to dd32:

... You'd be far better off implementing this as a plugin...

It this actually within the reach of a plugin?

One example for reasons a absolute url is easier, is when moving the site to another domain, You can simply replace all the site url's. With this solution, You can't reliably move it between directories,

This is wrong; please see comment# 3, or provide an example.

moving between hosts is fine, just as long as all paths end up the same. You'd also have to investigate Exports/Imports, as that would be affected too.

Good pointer.

Long story short, to me, It's not a problem that needs fixing, In the sense, that there are other solutions available already which fill the needs mentioned in this ticket. the output buffering items mentioned above are one method,

As mentioned the output buffering is not a solution, if you have a method that addresses comment# 14:

'with more testing it becomes clear that the ob_start options are unusable because it misses headers like those used in redirects to wp-login.php, and it gets urls it should not like the "siteurl" setting itself.'

my favourite method is to dynamically define WP_SITEURL/WP_HOME, or filter the siteurl option, or filter the site_url()/admin_url()/includes_url()/home_url() returns to respect the current hostname, etc.. there's always a method which suits the site/environment in question.

I'm not sure how one would do this can you provide an example?

Adding the close keyword again, to signify/track, that multiple developers have suggested it be closed, removing it doesn't change that decision. Also, It's a feature request to use root-relative links, as using absolute url's is not a bug, rather a decision.

We understand it's decision that was made for unknown reasons and if it's going to stay I would recommend at least checking for it and giving the user a warning instead of showing a partially broken page. As you mentioned a plugin would be ideal but I don't think it's within the power of a plugin so we will keep a patch for users to use regardless of if the core developers use it.

If edwardw's patch is polished a bit it would remove the only reasonable argument against changing to root relative urls ("it is work"), so it would be great if a dev could provide any other reason not to use root relative urls or better yet help him improve the patch.

#30 in reply to: ↑ 29 ; follow-ups: @dd32
13 years ago

Replying to dmole:

Replying to dd32:

... You'd be far better off implementing this as a plugin...

It this actually within the reach of a plugin?

Definately is possible, although not using your current approach of flaging at call time whether it's a link type that can have a root relative link, Using the methods i mentioned (see below)

One example for reasons a absolute url is easier, is when moving the site to another domain, You can simply replace all the site url's. With this solution, You can't reliably move it between directories,

This is wrong; please see comment# 3, or provide an example.

Original: http://clients.dd32.id.au/client1/; New: http://client.com.au/

Original: http://client.com.au/; New: http://clients.dd32.id.au/client3/

Long story short, to me, It's not a problem that needs fixing, In the sense, that there are other solutions available already which fill the needs mentioned in this ticket. the output buffering items mentioned above are one method,

As mentioned the output buffering is not a solution, if you have a method that addresses comment# 14:

'with more testing it becomes clear that the ob_start options are unusable because it misses headers like those used in redirects to wp-login.php, and it gets urls it should not like the "siteurl" setting itself.'

Redirects and url's within emails are not captured by output buffers.

my favourite method is to dynamically define WP_SITEURL/WP_HOME, or filter the siteurl option, or filter the site_url()/admin_url()/includes_url()/home_url() returns to respect the current hostname, etc.. there's always a method which suits the site/environment in question.

I'm not sure how one would do this can you provide an example?

add_filter('site_url', function($url) {
 if ( /* some logic to tell if you want to apply to this url, ie. whitelisted/blacklisted url endpoints, or apply to specific-type link hooks (they all have a hook) instead of site_url */ ) {
   $url_parts = parse_url($url); 
   $url = $url_parts['path'] . (array_key_exists('query',$url_parts) ? '?'.$url_parts['query'] : ''); 
 }
 return $url;
});

(Yes, That, in it's current form would apply to redirects and emails too. Perhaps you'd be best to check to see if the page is currently being output, ie. if ( did_action('wp_head') ), or language_attributes action, or similar)

If it's just different domains you want, and all generated links need to be domain-specific, You can do something like the following (I use it in conjuction with a few specific filters on some link generation types, from memory, i filter the themes and uploads (uploads to a CDN, themes to a common domain, static files from the theme to a CDN domain)) :

define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/');
define('WP_HOME', 'http://' . $_SERVER['SERVER_NAME'] . '/');
define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/wp-content');
// Add WP_PLUGINS_URL, THEMES URL, whatever else your particular setup needs

#31 in reply to: ↑ 30 @edwardw
13 years ago

Replying to dd32:

Original: http://clients.dd32.id.au/client1/; New: http://client.com.au/

Original: http://client.com.au/; New: http://clients.dd32.id.au/client3/

This is not a problem, as the root is clearly defined in the database as siteurl and home - you would just change http://clients.dd32.id.au/client1/ to http://client.com.au/ in the database. The relative URLs will be served relative to the roots defined here to ensure WordPress usability when accessed with more than one IP address/domain. Just to clarify, it is the root defined in the WordPress database, which doesn't have to always be / - it could be /blog, /wordpress or anything else.

#32 in reply to: ↑ 30 ; follow-up: @dmole
13 years ago

Replying to dd32:

example 1:

add_filter('site_url', function($url) {
 if ( true ) {
   $url_parts = parse_url($url); 
   $url = $url_parts['path'] . (array_key_exists('query',$url_parts) ?  '?'.$url_parts['query'] : ''); 
 }
 return $url;
});

This seems to work to slightly better than adwardw's patch, with only a bit more overhead, when added to wp-content/plugins/hello.php. the advantage is that it deals with headers properly, the problem is that we need "true" replaced with something to prevent changing the siteurl setting in the UI and some way to deal with emails. Any help with this would be greatly appreciated.

example 2:

define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/');
define('WP_HOME', 'http://' . $_SERVER['SERVER_NAME'] . '/');
define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/wp-content');

This did not work for me; adding this code to wp-content/plugins/hello.php makes links from http://127.0.0.1/wordpress/
point to http://random-page/ instead of http://127.0.0.1/wordpress/random-page/ or /wordpress/random-page/, I tried some variations but could not find something that worked, so I'll ignore it in favor of the first example.

#33 in reply to: ↑ 32 ; follow-up: @SergeyBiryukov
13 years ago

Replying to dmole:

This did not work for me; adding this code to wp-content/plugins/hello.php

It should be added to wp-config.php.

#34 in reply to: ↑ 33 ; follow-up: @dmole
13 years ago

Replying to SergeyBiryukov:

Replying to dmole:

This did not work for me; adding this code to wp-content/plugins/hello.php

It should be added to wp-config.php.

1) plugin said he was giving plugin examples.
2) where you add it makes no difference to the fact that it's killing WP_HOME
If would be nice if people tested stuff before commenting.

#35 @dmole
13 years ago

After trying dd32 2 examples in wp-config.php I realized I left the ob_start example in while testing before, so retesting make neither of them work, so we are back to edwardw's patch as the solution closest to working.

#36 in reply to: ↑ 34 ; follow-up: @SergeyBiryukov
13 years ago

Replying to dmole:

where you add it makes no difference to the fact that it's killing WP_HOME

WP_HOME and WP_SITEURL are really meant to be defined in wp-config.php, check #4003.

If would be nice if people tested stuff before commenting.

I've been using them for quite a while. You may have something else left from previous testing.

#37 in reply to: ↑ 36 ; follow-up: @dmole
13 years ago

Replying to SergeyBiryukov:

I've been using them for quite a while.

In that case can you provide an example of the 2 URLs you visit your WP install with and what code you used to get it to work, and where you put the code?

#38 @nacin
13 years ago

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

Feel free to continue discussion here or elsewhere, but re-closing this.

#39 in reply to: ↑ 37 @SergeyBiryukov
13 years ago

Replying to dmole:

In that case can you provide an example of the 2 URLs you visit your WP install with and what code you used to get it to work, and where you put the code?

I mainly use them for local development.

Suppose production site is example.com.

To create a local copy, I import the database, copy wp-content and put this into wp-config.php:

define( 'WP_HOME', 'http://'. $_SERVER['HTTP_HOST'] );
define( 'WP_SITEURL', 'http://'. $_SERVER['HTTP_HOST'] );

Which allows me to use any domain pointing to that directory (e.g. example.projects).

I'm not sure if these constants will actually help you to achieve your goals with this ticket. Maybe not, so add_filter('site_url', ...) works better for you. I only commented because it's a valid way to redefine home and siteurl values in some scenarios.

#40 @AmbushCommander
13 years ago

Note that relative URLs break TinyMCE. I suspect users who were using relative URLs are seeing this, see: http://wordpress.org/support/topic/problems-with-visual-editor-in-wp-31/page/3?replies=85

#41 @dmole
13 years ago

Seeing as there is not yet a solid solution for using "WordPress root" relative URLs it's pointless to look at the effects of hacks on plugins like TinyMCE.

What SergeyBiryukov is using will defiantly cause problems and not work at all with some configs.

I would love someone to come up with a solid solution (plugin support aside), because all we have in this thread so far are well intentioned hacks that don't quite fully work.

We do however have 4 different approaches that could in the hands of the right person lead to a solid solution.

#42 @edwardw
13 years ago

Just for the record, phpBB uses relative (..) style URLs and MediaWiki uses root relative URLs (e.g. /wiki/Main_Page). It would be nice for WordPress to follow suit, but until the "later" in "maybelater" comes we will probably have to attempt to solve this using a source-code hack or some form of a plugin.

#44 @MarcusPope
12 years ago

@SergeyBiryukov - any chance that ticket (my patch) will make it into 3.3?

For the rest of you:

Since it was referenced here I figure I'll add my $.02. This problem is laughable in the development circles I work in. The idea that Wordpress core members don't see the value of root-relative URLs or the pitfalls of absolute URLs literally makes people laugh when I tell them. Mostly because this is a problem that was solved in enterprise web development platforms well over a decade ago.

However, to cheer up those who desire this functionality I just wanted to inform you that I have solved the problem via a plugin and wp-config.php change for vanilla installs. It has been tested and we currently use it on a couple of production sites. If #18910 is ever reviewed and added to the core, it will work for MU path-based installs too. Subdomain based MU sites are screwed because of the severe lack of judgement on WP's part, but I will aim to solve that too with a complete fork of 3.3 when it's released.

To the core members who suggest things like output buffering and defining WP_HOME/SITEURL - those hacks make the problem even worse. Try them out and run a packet sniffer while you do so to see what I'm referring to. Additionally try using the site from both urls at the same time over a couple of weeks and watch your content become a mish-mash of various URLs that result in 404s and a broken user experience. You obviously don't understand the problem if you think these solutions are viable in a production environment. And you have obviously never tried to login to the admin section if you think output buffering is all you need (ahem @nacin)

In reality this plugin requires hooking into 20 different hooks and doing an unecessarily excessive amount of transformations on urls (and really the core does an unecessarily excessive amount of transformations on urls without this plugin - aka HTTP/HTTPS.) I'm not sure how well it would scale for larger sites (thousands of pages or more than 50 plugins,) but it's at least a viable option for now where as before there was not one.

In addition to publishing this plugin very soon (probably tomorrow if not tonight) I'm also in the process of writing a full synopsis on this problem and the viewpoints of everyone involved. It will include some criticism on the WP core team members for outright ignoring completely valid points made by the community. Additionally it covers topics yet to be discussed, like being unable to test development changes from an iPhone or other mobile device in a local-only staging environment without network level NAT configuration (something that isn't very common on most WIFI routers.)

Ultimately a "design decision" can also be a "bad design decision" that needs to be changed. And in this case you should listen a little more to your community.

http://wordpress.org/extend/plugins/root-relative-urls/

I'm wrapping up the readme docs today and will publish it by tomorrow at the latest.

-Marcus

#45 follow-up: @nacin
12 years ago

I've been waiting for you to comment here since I approved your plugin two days ago. Good luck with it.

#46 @ryan
12 years ago

WP has used absolute URLs since the b2 days. If I had a time machine, it probably wouldn't. The main reason it still uses absolute urls is because changing doesn't seem worth the pain. The points here haven't been ignored, they just aren't enough to make most us want to mess with this when we could be doing things that people beyond those hanging out in easily amused developer circles care about. If someone wants to patch core in a manner that is fully back compat with existing URL and PATH constants as well as existing values in the DB, I'd be interested in seeing the result.

#47 follow-up: @dmole
12 years ago

  • Version changed from 3.1 to 3.3

so 7 months later
1) It's clear this should be implemented and that it's priority is rather low.
2) It's obvious we need to update the core to fix this properly.
3) we have 6+ core contributors in this thread but no one has made a patch or fork yet.

(MarcusPope thanks for the partial fix via plugin, I hope the link to your plugin starts working soon.)

updating this to a 3.3 problem and leaving as closed, hoping it will be fixed "maybelater" despite it's closed state.

#48 @MarcusPope
12 years ago

@ryan - It may not seem worth the pain to you, but it has and will continue to prevent wordpress from being a serious contender in a majority of enterprise situations for reasons that are exclusive to an unmanageable build & deployment process.

Several points, like internal v external NAT translations, reverse-proxies, ip access on load-balanced configurations or even just hosting multiple tld sites on one installation have in fact been ignored.

And honestly the amount of code surrounding all of the URL & PATH constants, and HTTP/S hacks, and the very existence of those values permeating the DB are pretty much proof positive that more pain was added to the equation than would have been necessary to refactor it back in 2007 when this concept was first proposed (possibly even earlier than that.)

I applaud your honesty in recognizing the value in a root-relative design, you're the first to do so without making up excuses that it can't possibly be done - ala dd32. And feel free to assume we are an easily amused group. But expecting a hero to come change the entire underlying architecture for your interested review doesn't start with the feedback we've seen here.

Ideally we'd see a forked version that the entire group stands behind because it's the proper way to do it. Users would have a choice of when to migrate. And eventually the lesser of the designs would be sunsetted. Root-relative urls are 99% identical to absolute URLs so the mass casualties are not likely. And if a plugin doesn't work as a result it's most likely because it operates on the same flawed assumptions and needs to change as well.

#49 in reply to: ↑ 45 ; follow-up: @MarcusPope
12 years ago

Replying to nacin:

I've been waiting for you to comment here since I approved your plugin two days ago. Good luck with it.

Yeah, work got in the way. But it's about to go up.

@dmole - you're welcome, it will make your wordpress life so much easier I promise. :D

#50 in reply to: ↑ 49 @edwardw
12 years ago

Replying to MarcusPope:

Replying to nacin:

I've been waiting for you to comment here since I approved your plugin two days ago. Good luck with it.

Yeah, work got in the way. But it's about to go up.

@dmole - you're welcome, it will make your wordpress life so much easier I promise. :D

Now that we've got a plugin solution, does anyone want to continue work on the existing test-patch or somehow find a more elegant way to make a permanent fix in core?

Also this should get some core devs' attention - this is doable, but any plugin or patch will just become stable unless we can get core traction behind this.

Looking forward to your comment on this.

#51 @MarcusPope
12 years ago

I'm fairly confident that I can wrangle the fix with or without core group support. But I was going to wait until 3.3 was released and stable before attempting such a feat because there will be a lot of changes that add value to the system, and why exclude them this late in the game.

What I intended to do with it from there was yet to be decided. Options like taking the wpengine.com route, or simply using it as the foundation for future projects we work on here at springbox.com were in the mix. I would of course offer the patch to wordpress.org, but before @Ryan commented I didn't think it would be of much use to them.

I've never been a fan of forking to compete but offering the platform as an Enterprise-Edition didn't really seem like a competition.

I can say that the likelihood of this plugin breaking (as a result of core developments) is not very likely given that it operates on standard filters at some of the lowest points in the core.

However I do remember now that there are a couple *_link_* functions (like comments_link_feed()) in feed.php that do not get a custom filter applied in the way that 'the_permalink_rss' does - so already I have just discovered a bug that would require a core hack to make this plugin work 100% :(

Oh well worse things have happened than not being able to click a link on an rss feed that goes directly to the comments.

But I figure that discussion should probably migrate away from this ticket, perhaps back into the wp-hackers list. My email is marcus.pope at springbox dawt com if anyone would like to discuss options for moving forward.

#52 follow-up: @MarcusPope
12 years ago

Oh, and the plugin is now available for download, so enjoy!

http://wordpress.org/extend/plugins/root-relative-urls/

#53 in reply to: ↑ 52 @edwardw
12 years ago

Replying to MarcusPope:

Oh, and the plugin is now available for download, so enjoy!

http://wordpress.org/extend/plugins/root-relative-urls/

Just tried the plugin, and it pretty much accomplishes pretty much what my test patch and the core devs' hacky fixes (WP_HOME/WP_SITEURL). My main concern right now is that previous content (internal posts, media, images/video) is not automatically updated - for example, if previously server was based off internal1.example.com it would break to outsiders looking at blog.example.com (Although I'm sure we can always find&replace in the database for old posts)

Also a nice enhancement, but not necessary (would help with web mirroring, but that's going off a bit on a tangent) would be to use relative URLs directly in page source - instead of

<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://internal1.example.com/wordpress/wp-includes/wlwmanifest.xml" />

we can go directly to this:

<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="/wordpress/wp-includes/wlwmanifest.xml" />

Finally, which domain gets to be the "preferred" one for sending out e-mails? Right now on my development server it seems to the the one I installed from.

#54 follow-up: @MarcusPope
12 years ago

For sending out emails - it's the host that is serving the content. That will dynamically change depending on where you are hosting from (dev, staging or production.) So you can safely send out emails from a dev environment without affecting your production users.

Not changing existing content is a recognized caveat. There are a couple plugins out there that do accomplish this, and if used in combination with my plugin they *might* update to root-relative links if they are implemented properly. Adding a feature to look for a user inputed "http://internal1.example.com" and replace it with "" in the database should be doable, but it was outside the scope of what I needed when I wrote the plugin. As it stands, since the SITE_URL is now dynamic, I can't reliably know what to look for programmatically because in dev, I wouldn't know what your production links are supposed to be.

The wlwmanifest is actually pulled from the site_url() - because site_url is used in ways that are not applicable to root-relative only links it has to be dynamically generated with the current HTTP_HOST. But it's not a huge problem because that internal1.example.com will change depending on the host it is being served from, which is essentially what a root-relative url does anyway.

It's a shame there's not a comments thread on the plugin page itself, as I feel awkward posting here for support. Is the only other option my own solution or constantly trolling the support message board to look for my plugin's tag?

#55 in reply to: ↑ 54 @edwardw
12 years ago

Replying to MarcusPope:
E-mail perhaps?

#56 @dd32
12 years ago

Is the only other option my own solution or constantly trolling the support message board to look for my plugin's tag?

There's a few RSS feeds in your profile to help you follow support requests: http://wordpress.org/extend/plugins/profile/MarcusPope - But yes, Please don't use the WordPress Trac as a support avenue for plugins, by all means, continue to discuss moving this ticket forward here, but try to keep anything plugin-specific to the forums (To keep it easier to follow the ticket)

#57 @mikeschinkel
12 years ago

  • Cc mikeschinkel@… added

#58 @marcuspope
12 years ago

Aha! Thanks @dd32 i've been looking for a link like that for a couple days nows. @edwardw my email is posted above, but it's cryptic. marcus.pope at springbox dawt com.

#59 in reply to: ↑ 47 @SergeyBiryukov
12 years ago

  • Version changed from 3.3 to 3.1

Replying to dmole:

updating this to a 3.3 problem

Version field is used to track when a issue was first raised, not whether it still exists in current version. It should not be changed to a later version if it affects the earlier versions.

#60 @markus.magnuson
11 years ago

  • Cc markus.magnuson@… added

This ticket was mentioned in Slack in #core by helen. View the logs.


9 years ago

#62 follow-up: @lukecavanagh
8 years ago

Seems like the plugin mentioned in this ticket, does not work with the current version of WP and was last updated two years ago. Is this something that is worth looking at again?

#63 in reply to: ↑ 62 @MacKiller
7 years ago

Replying to lukecavanagh:

Seems like the plugin mentioned in this ticket, does not work with the current version of WP and was last updated two years ago. Is this something that is worth looking at again?

Yes, please! I've been reading extensively all of the discussion around the topic, and my humble vote would be to see this request revisited.

At an enterprise level, I have multiple programmers working on the same website. I can't use hosts file overrides, because we are doing integration work, and those cloud services need to be able to call back to the dev servers, and I don't have that many external IPs to dedicate to this. Furthermore, we use git to collaborate into creating one working solution. The hard-coded absolute addresses are creating significant roadblocks for enterprise level cloud development.

By the way, thank you for all the work on an amazing product.

#64 @swissspidy
7 years ago

#37723 was marked as a duplicate.

#65 @lukecavanagh
7 years ago

@lukecavanagh

Seems like there is a forked version of the plugin.

https://github.com/Hube2/root-relative-urls

#66 @johnbillion
5 years ago

#45230 was marked as a duplicate.

#67 @sabernhardt
20 months ago

#51500 was marked as a duplicate.

Note: See TracTickets for help on using tickets.