wp_http_validate_url()WP 3.5.2

Checks if the specified URL can be used in an HTTP request, for example in the HTTP API.

  • The URL will not pass the check (will return false) if:

    • The URL specifies an incorrect protocol (different from http/https): see the function wp_kses_bad_protocol()
    • The provided URL could not be parsed using the PHP function parse_url().
    • The domain name contains the character: :#?[]
    • The URL specifies a user or password (user/pass).
    • The domain in the specified URL differs from the current site domain (external URL) and the obtained IP of the external domain is internal (localhost). Internal URLs can be allowed through the filter: http_request_host_is_external.
  • The URL will pass the check (will return the specified URL) if all the above checks are passed and:

    • No port is specified in the URL,
    • or a port is specified and it is equal to one of: 80, 443, 8080,
    • or the site domain is equal to the URL domain and the site domain port matches the port of the specified URL.
1 time — 0.003391 sec (very slow) | 50000 times — 7.47 sec (fast) | PHP 7.1.11, WP 4.9.5

Returns

String|false. The provided URL or false if the URL did not pass the check.

Usage

$url = wp_http_validate_url( $url );
$url(string) (required)
The URL to be checked and sanitized.

Examples

0

#1 Demonstration of checks for different URL variants

// internal URL
echo wp_http_validate_url('wp-kama.ru'); // false
echo wp_http_validate_url('https://wp-kama.ru'); // https://wp-kama.ru

// external URL
echo wp_http_validate_url('site.com'); // false
echo wp_http_validate_url('http://example.com'); // http://example.com

// URL with user and password
echo wp_http_validate_url('http://username:[email protected]/'); // false

// URL with port
echo wp_http_validate_url('http://example.com:80/'); // http://example.com:80/
echo wp_http_validate_url('http://example.com:123/'); // false
0

#2 Another variant of validating a URL

If you’re validating a URL submitted by a user, I’d suggest instead using esc_url_raw(). Like so:

esc_url_raw( $url ) === $url

Changelog

Since 3.5.2 Introduced.

wp_http_validate_url() code WP 6.9

function wp_http_validate_url( $url ) {
	if ( ! is_string( $url ) || '' === $url || is_numeric( $url ) ) {
		return false;
	}

	$original_url = $url;
	$url          = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
	if ( ! $url || strtolower( $url ) !== strtolower( $original_url ) ) {
		return false;
	}

	$parsed_url = parse_url( $url );
	if ( ! $parsed_url || empty( $parsed_url['host'] ) ) {
		return false;
	}

	if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) ) {
		return false;
	}

	if ( false !== strpbrk( $parsed_url['host'], ':#?[]' ) ) {
		return false;
	}

	$parsed_home = parse_url( get_option( 'home' ) );
	$same_host   = isset( $parsed_home['host'] ) && strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );
	$host        = trim( $parsed_url['host'], '.' );

	if ( ! $same_host ) {
		if ( preg_match( '#^(([1-9]?\d|1\d\d|25[0-5]|2[0-4]\d)\.){3}([1-9]?\d|1\d\d|25[0-5]|2[0-4]\d)$#', $host ) ) {
			$ip = $host;
		} else {
			$ip = gethostbyname( $host );
			if ( $ip === $host ) { // Error condition for gethostbyname().
				return false;
			}
		}
		if ( $ip ) {
			$parts = array_map( 'intval', explode( '.', $ip ) );
			if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0]
				|| ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
				|| ( 192 === $parts[0] && 168 === $parts[1] )
			) {
				// If host appears local, reject unless specifically allowed.
				/**
				 * Checks if HTTP request is external or not.
				 *
				 * Allows to change and allow external requests for the HTTP request.
				 *
				 * @since 3.6.0
				 *
				 * @param bool   $external Whether HTTP request is external or not.
				 * @param string $host     Host name of the requested URL.
				 * @param string $url      Requested URL.
				 */
				if ( ! apply_filters( 'http_request_host_is_external', false, $host, $url ) ) {
					return false;
				}
			}
		}
	}

	if ( empty( $parsed_url['port'] ) ) {
		return $url;
	}

	$port = $parsed_url['port'];

	/**
	 * Controls the list of ports considered safe in HTTP API.
	 *
	 * Allows to change and allow external requests for the HTTP request.
	 *
	 * @since 5.9.0
	 *
	 * @param int[]  $allowed_ports Array of integers for valid ports. Default allowed ports
	 *                              are 80, 443, and 8080.
	 * @param string $host          Host name of the requested URL.
	 * @param string $url           Requested URL.
	 */
	$allowed_ports = apply_filters( 'http_allowed_safe_ports', array( 80, 443, 8080 ), $host, $url );
	if ( is_array( $allowed_ports ) && in_array( $port, $allowed_ports, true ) ) {
		return $url;
	}

	if ( $parsed_home && $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $port ) {
		return $url;
	}

	return false;
}