Page MenuHomePhabricator

Use relative URL for local redirects in OutputPage
Open, MediumPublic

Description

Background

  1. https://en.m.wiktionary.org/wiki/Wiktionary:Main_Page
  2. Search for "banana" and click first result. This navigates to https://en.m.wiktionary.org/w/index.php?title=Special%3ASearch&search=banana (as expected, stays on m-dot)
  3. the search handler in MediaWiki core this finds an exact match for the /wiki/banana page, and redirects to it.
  4. the OutputPage class in MediaWiki changes this and expands it to the canonical URL at https://en.wiktionary.org/wiki/Wiktionary:Main_Page, instead of sending it to the browser as-is where it would be interpreted as a relative URL based on the curent domain.

The code in OutputPage.php#output:

	// Modern standards don't require redirect URLs to be absolute, but make it so just in case.
	// Note that this doesn't actually guarantee an absolute URL: relative-path URLs are left intact.
	$redirect = (string)…UrlUtils()->expand( $this->mRedirect, PROTO_CURRENT );
	// ...
	$response->statusHeader( (int)$code );
	// ...
	$response->header( 'Location: ' . $redirect );

This code was added in 2003, with a minor change in 2008 (SVN r30898, Git diff, T14981, T14935).

From SVN r2231:

Force redirect headers to use absolute URLs as per spec (though
browsers seem to accept relative ones);

... which suggests there was not a specific risk or concern at the time.

A few years later the spec was updated to reflect reality, thus applying not only to browsers but all HTTP clients. Relative URL redirects work as expected in Curl, Node.js, Python, etc.

From Wikipedia:

An obsolete version of the HTTP 1.1 specifications (IETF RFC 2616) required a complete absolute URI for redirection. The IETF HTTP working group found that the most popular web browsers tolerate the passing of a relative URL and, consequently, the updated HTTP 1.1 specifications (IETF RFC 7231) relaxed the original constraint, allowing the use of relative URLs in Location headers.

From RFC 7131, dated 2014:

The syntax of the Location header field has been changed to allow all URI references, including relative references and fragments, along with some clarifications as to when use of fragments would not be appropriate.

Problem

  • It would require keeping separate CDN cache variants, whereas we could otherwise share and consolidate the mdot-mobile and unified-mobile cache objects, per T405931.
  • It means people are perceiving an "m-dot to standard" redirect today already, even though we have not yet deployed any such redirect as part of T405931. Quote: "after a search, the .m gets stripped automatically" as reported on the Wiktionary:Feedback forum earlier this week.
  • It is jarring to be taken to a different domain.

Proposal

Remove the expand URL step from OutputPage::output.

Note that this change will not not apply to rest.php and other API responses. We may want to maintain more "just in case" compatibility with those as they are used by lots of clients. In any case, that's out of scope for this task.

I'm not aware of significant non-browser use cases to hit the Special:Search redirect, as it sits between two parts of the search GUI neither of which are meant to be indexed by crawlers or otherwise shared directly. Even if you right-click the search result and copy, you'll get an absolute URL as per the browser expanding it. Note that all anchor links in MediaWiki parser output are relative links by default today as well, e.g.:

<a href="/wiki/Banana">..</a>

If there are specific redirects we're concerned about that do make it through OutputPage, we could UrlUtils::expand() on one or to of those explicitly rather than centrally on everything.

Related:

Event Timeline

Krinkle claimed this task.
Krinkle triaged this task as Medium priority.
Krinkle added a subscriber: tstarling.

Change #1197928 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/core@master] OutputPage: Remove UrlUtils::expand call from redirect destination

https://gerrit.wikimedia.org/r/1197928

Change #1197981 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/core@master] title,search: Prefer local URL for local pages in getFullUrlForRedirect

https://gerrit.wikimedia.org/r/1197981

Change #1197983 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/extensions/GrowthExperiments@master] SpecialMentorDashboard: Make getFullURL redirect explicit

https://gerrit.wikimedia.org/r/1197983

Change #1197989 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/extensions/GrowthExperiments@master] SpecialMentorDashboard: Make getFullURL redirect explicit

https://gerrit.wikimedia.org/r/1197989

Change #1197989 merged by jenkins-bot:

[mediawiki/extensions/GrowthExperiments@master] SpecialMentorDashboard: Make getFullURL redirect explicit

https://gerrit.wikimedia.org/r/1197989

With the demise of Wikimedia m. domains, the original problem statement seems to be no longer relevant, but I suppose you could encounter the same problem if you had a wiki accessible from two different domains for any reason, and $wgServer was not configured dynamically depending on the domain through which the wiki was accessed.

Change #1197928 merged by jenkins-bot:

[mediawiki/core@master] OutputPage: Remove UrlUtils::expand call from redirect destination

https://gerrit.wikimedia.org/r/1197928

Change #1266481 had a related patch set uploaded (by SomeRandomDeveloper; author: SomeRandomDeveloper):

[mediawiki/extensions/CreatePageUw@master] Don't expect expanded redirect URLs in unit tests

https://gerrit.wikimedia.org/r/1266481

Change #1266481 merged by jenkins-bot:

[mediawiki/extensions/CreatePageUw@master] Don't expect expanded redirect URLs in unit tests

https://gerrit.wikimedia.org/r/1266481