wp_validate_redirect()WP 2.8.1

Validates a URL for use in a redirect.

Checks whether the $location is using an allowed host, if it has an absolute path. A plugin can therefore set or remove allowed host(s) to or from the list.

If the host is not allowed, then the redirect is to $fallback_url supplied.

Pluggable function — this function can be replaced from a plugin. It means that this function is defined (works) only after all plugins are loaded (included), but before this moment this function has not defined. Therefore, you cannot call this and all functions depended on this function directly from a plugin code. They need to be called on plugins_loaded hook or later, for example on init hook.

Function replacement (override) — in must-use or regular plugin you can create a function with the same name, then it will replace this function.

1 time — 0.003549 sec (very slow) | 50000 times — 2.44 sec (fast) | PHP 7.0.32, WP 5.1.1
Hooks from the function

Return

String. Redirect-sanitized URL.

Usage

wp_validate_redirect( $location, $fallback_url );
$location(string) (required)
The redirect to validate.
$fallback_url(string)
The value to return if $location is not allowed.
Default: ''

Examples

0

#1 Demo

It is assumed that the function was launched at example.com.

echo wp_validate_redirect( 'http://foo.bar' );                    //> ''
echo wp_validate_redirect( 'http://foo.bar', 'http://my.site' );  //> http://my.site
echo wp_validate_redirect( '//example.com/foo' );                 //> http://example.ru/foo
echo wp_validate_redirect( 'https://example.com/foo' );           //> https://example.ru/foo

Changelog

Since 2.8.1 Introduced.

wp_validate_redirect() code WP 6.5.3

function wp_validate_redirect( $location, $fallback_url = '' ) {
	$location = wp_sanitize_redirect( trim( $location, " \t\n\r\0\x08\x0B" ) );
	// Browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'.
	if ( str_starts_with( $location, '//' ) ) {
		$location = 'http:' . $location;
	}

	/*
	 * In PHP 5 parse_url() may fail if the URL query part contains 'http://'.
	 * See https://bugs.php.net/bug.php?id=38143
	 */
	$cut  = strpos( $location, '?' );
	$test = $cut ? substr( $location, 0, $cut ) : $location;

	$lp = parse_url( $test );

	// Give up if malformed URL.
	if ( false === $lp ) {
		return $fallback_url;
	}

	// Allow only 'http' and 'https' schemes. No 'data:', etc.
	if ( isset( $lp['scheme'] ) && ! ( 'http' === $lp['scheme'] || 'https' === $lp['scheme'] ) ) {
		return $fallback_url;
	}

	if ( ! isset( $lp['host'] ) && ! empty( $lp['path'] ) && '/' !== $lp['path'][0] ) {
		$path = '';
		if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
			$path = dirname( parse_url( 'http://placeholder' . $_SERVER['REQUEST_URI'], PHP_URL_PATH ) . '?' );
			$path = wp_normalize_path( $path );
		}
		$location = '/' . ltrim( $path . '/', '/' ) . $location;
	}

	/*
	 * Reject if certain components are set but host is not.
	 * This catches URLs like https:host.com for which parse_url() does not set the host field.
	 */
	if ( ! isset( $lp['host'] ) && ( isset( $lp['scheme'] ) || isset( $lp['user'] ) || isset( $lp['pass'] ) || isset( $lp['port'] ) ) ) {
		return $fallback_url;
	}

	// Reject malformed components parse_url() can return on odd inputs.
	foreach ( array( 'user', 'pass', 'host' ) as $component ) {
		if ( isset( $lp[ $component ] ) && strpbrk( $lp[ $component ], ':/?#@' ) ) {
			return $fallback_url;
		}
	}

	$wpp = parse_url( home_url() );

	/**
	 * Filters the list of allowed hosts to redirect to.
	 *
	 * @since 2.3.0
	 *
	 * @param string[] $hosts An array of allowed host names.
	 * @param string   $host  The host name of the redirect destination; empty string if not set.
	 */
	$allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array( $wpp['host'] ), isset( $lp['host'] ) ? $lp['host'] : '' );

	if ( isset( $lp['host'] ) && ( ! in_array( $lp['host'], $allowed_hosts, true ) && strtolower( $wpp['host'] ) !== $lp['host'] ) ) {
		$location = $fallback_url;
	}

	return $location;
}