Page MenuHomePhabricator

Special pages don't display Mediawiki:redirectfrom (aka mw-redirectfrom) when redirected to
Open, LowPublicBUG REPORT

Description

Steps to replicate the issue:

  • Create a redirect to a special page, e.g. redirect [[SP:SP]] as a shortcut to [[Special:SpecialPages]]. This can only be done on some wikis that permit this, where $wgDisableHardRedirects=false (see below)
  • Type the redirect into the search box and press enter.

What happens?:

The redirect works as intended, πŸ‘ but doesn't display [[Mediawiki:Redirectfrom]] πŸ˜”

What should have happened instead?:

It should display [[Mediawiki:Redirectfrom]] below the page title, like other redirects.

Impact on $wgDisableHardRedirects

The setting $wgDisableHardRedirects disables two different things. It disables interwiki redirects, but it also disables redirects to special pages. This is legacy code from 2006. It violates the Single Responsibility Principle, and it's somewhat opaque as to what exactly a hard redirect is. Both contribute to Technical-Debt

Shortcut redirects to special pages do make some sense (πŸ‘). It's convenient to type in a shortcut into the search box and press enter. But third-party wikis really do not want users to be whisked off to a completely different website, that's not controlled by the 3rd party, without warning having clicked on a normal-looking blue link (🀦).

Setting up redirects to special pages so that they work properly means that this situation can be fixed by splitting $wgDisableHardRedirects per T395326: `$wgDisableHardRedirects` should be split into 2 config settings.

Notes
At present, mw-redirectfrom is only called from includes/page/Article.php. The code looks something like this:

	public function showRedirectedFromHeader() {
		$context = $this->getContext();
		$redirectSources = $context->getConfig()->get( MainConfigNames::RedirectSources );
		$outputPage = $context->getOutput();
		$request = $context->getRequest();
		$rdfrom = $request->getVal( 'rdfrom' );
		// Construct a URL for the current page view, but with the target title
		$query = $request->getQueryValues();
		unset( $query['rdfrom'] );
		unset( $query['title'] );
		if ( $this->getTitle()->isRedirect() ) {
			// Prevent double redirects
			$query['redirect'] = 'no';
		}
		$redirectTargetUrl = $this->getTitle()->getLinkURL( $query );
		if ( $this->mRedirectedFrom ) {
			// This is an internally redirected page view.
			// We'll need a backlink to the source page for navigation.
			if ( $this->getHookRunner()->onArticleViewRedirect( $this ) ) {
				$redir = $this->linkRenderer->makeKnownLink(
					$this->mRedirectedFrom,
					null,
					[],
					[ 'redirect' => 'no' ]
				);
				$outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
					$context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
				. "</span>" );
				// Add the script to update the displayed URL and
				// set the fragment if one was specified in the redirect
				$outputPage->addJsConfigVars( [
					'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
				] );
				$outputPage->addModules( 'mediawiki.action.view.redirect' );
				// Add a <link rel="canonical"> tag
				$outputPage->setCanonicalUrl( $this->getTitle()->getCanonicalURL() );
				// Tell the output object that the user arrived at this article through a redirect
				$outputPage->setRedirectedFrom( $this->mRedirectedFrom );
				return true;
			}
		} elseif ( $rdfrom ) {
			// This is an externally redirected view, from some other wiki.
			// If it was reported from a trusted site, supply a backlink.
			if ( $redirectSources && preg_match( $redirectSources, $rdfrom ) ) {
				$redir = $this->linkRenderer->makeExternalLink( $rdfrom, $rdfrom, $this->getTitle() );
				$outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
					$context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
				. "</span>" );
				// Add the script to update the displayed URL
				$outputPage->addJsConfigVars( [
					'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
				] );
				$outputPage->addModules( 'mediawiki.action.view.redirect' );
				return true;
			}
		}
		return false;
	}
  • This function needs to be called from both includes/page/Article.php AND includes/specialpage/SpecialPage.php
  • It might be a good idea to move this function into its own include, but then we need to decide (1) where it goes and (2) what to call it. Please discuss:
  • Keep it in the same place
  • Move it into its own include, located where and called what?
  • Move it into MediaWiki\Rest\Handler\RedirectHandler (which is the code that does the actual redirecting)

Thanks.

Event Timeline

Reedy renamed this task from Redirects to special pages don't display [[Mediawiki:redirect from]] to Redirects to special pages doesn't display [[Mediawiki:redirect from]].Jan 1 2023, 12:08 PM
Reedy added a project: MediaWiki-Redirects.

@Bugreporter2: A good first task is a self-contained, non-controversial task with a clear approach. It should be well-described with pointers to help a completely new contributor. Given the current short task description I'm removing the good first task tag. Please add details what exactly has to happen where and how for a new contributor, and then add back the good first task project tag. Thanks a lot in advance!

Bugreporter2 renamed this task from Redirects to special pages doesn't display [[Mediawiki:redirect from]] to Redirects to special pages don't display [[Mediawiki:redirect from]].Jan 25 2025, 9:29 AM
Bugreporter2 updated the task description. (Show Details)
Bugreporter2 updated the task description. (Show Details)
Bugreporter2 awarded a token.
Bugreporter2 renamed this task from Redirects to special pages don't display [[Mediawiki:redirect from]] to Redirects to special pages don't display Mediawiki:redirectfrom (aka mw-redirectfrom).Jan 30 2025, 8:10 AM
Bugreporter2 updated the task description. (Show Details)

@Aklapper , I've updated the task description to explain this self-contained, non-controversial task with a clear approach. It is well-described with pointers to help a completely new contributor. Is the task too complex for new contributors?

Bugreporter2 renamed this task from Redirects to special pages don't display Mediawiki:redirectfrom (aka mw-redirectfrom) to Special pages don't display Mediawiki:redirectfrom (aka mw-redirectfrom) when redirected to.Aug 9 2025, 6:24 AM

This hasn't received much attention, but I think it's important because it allows other fixes downstream.

I also think it mostly involves moving a bit of code around, which doesn't seem too complicated, but where to move it to is an issue that I'd appreciate comments on.

So if you don't mind, I'd like a few minutes of your time, @Umherirrender @matmarex as the β€œblame” indicates that you wrote the function.

  1. Does it actually need to be moved?
  2. If yes, move it into its own include, located where and called what?
  3. Maybe move it into MediaWiki\Rest\Handler\RedirectHandler (which is the code that does the actual redirecting)

Thanks.

The important difference between normal redirects to articles and redirects to special pages is that in normal redirects, the target page is shown by MediaWiki without doing a HTTP redirect, so MediaWiki has the information about the redirect title while displaying the target page and can add it to the subtitle – while in case of redirects to special pages, MediaWiki emits a HTTP redirect, the browser fetches the new URL, and when that happens MediaWiki no longer knows which redirect title we arrived from. The relevant code is in ActionEntryPoint here, which calls WikiPage::followRedirect() and getRedirectURL().

This is something you would have to solve first. I don't think we should change it to not do a HTTP redirect (special pages often have different access restrictions and caching rules from normal pages, so mixing up the processing seems like it could easily cause bugs). Possibly you could add a URL parameter to the redirect, similar to 'rdfrom' used for interwiki redirects, and then handle that in the special page code (maybe in SpecialPage::setHeaders). We probably shouldn't try to share this code with the Article class: I expect that it will be similar, but with plenty of subtle differences.

MediaWiki\Rest\Handler\RedirectHandler is not relevant here, as it is only used by the REST API.

BTW I agree that it would make sense to split DisableHardRedirects into two config settings (T395326). That should be much easier to do.

πŸ™πŸ™πŸ™ Thanks for the consideration and feedback @matmarex. (and @ Umherirrender who I won't at, as that'll re-subscribe them to the task)

I will refactor the tasks to take your comments into consideration. This one isn't as straightforward as it appeared to be.