WC_REST_Authentication::route_from_request_uri │ private │ WC 11.1.0

The REST route the request URI points to, normalized the way WordPress matches it.

Returns the route without the REST prefix or surrounding slashes, e.g. 'wc/v3/products'. The path is read unconditionally; a route named in the query string is only trusted once wp_is_rest_endpoint() confirms genuine REST dispatch, and returns an empty string until then.

Method of the class: WC_REST_Authentication{}

No Hooks.

Returns

string.

Usage

// private - for code of main (parent) class only
$result = $this->route_from_request_uri();

Changelog

Since 11.1.0 Introduced.

WC_REST_Authentication::route_from_request_uri() code WC 11.1.2

private function route_from_request_uri() {
	if ( empty( $_SERVER['REQUEST_URI'] ) ) {
		return '';
	}

	$rest_prefix = trailingslashit( rest_get_url_prefix() );

	/*
	 * Parse the raw URI, not an esc_url_raw() copy. This decides whether an API key may
	 * authenticate the request, so it has to read the URI the way WordPress routes on it.
	 * esc_url_raw() rewrites its input, so the route derived from an escaped copy is not always
	 * the route that gets served. Only parsed and compared here, never output, so no escaping is
	 * needed.
	 */
	// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Parsed and compared against REST route prefixes only, never output or stored; sanitizing would diverge from the route WordPress dispatches.
	$request_uri = wp_unslash( $_SERVER['REQUEST_URI'] );

	// WP::parse_request() trims leading slashes off the URI, but wp_parse_url() would read a
	// leading '//' as a host, so collapse them first.
	if ( str_starts_with( $request_uri, '//' ) ) {
		$request_uri = '/' . ltrim( $request_uri, '/' );
	}

	$query_string = wp_parse_url( $request_uri, PHP_URL_QUERY );
	$query_params = array();

	if ( is_string( $query_string ) ) {
		parse_str( $query_string, $query_params );
	}

	// Plain permalinks can carry the route in the query string.
	if ( isset( $query_params['rest_route'] ) ) {
		// Only trust and read it once dispatch is confirmed and it's a single value.
		if ( ! wp_is_rest_endpoint() || ! is_string( $query_params['rest_route'] ) ) {
			return '';
		}

		return trim( $query_params['rest_route'], '/' );
	}

	$request_path = wp_parse_url( $request_uri, PHP_URL_PATH );

	if ( ! is_string( $request_path ) ) {
		return '';
	}

	// Strip the site's home path the way WP::parse_request() does, so subdirectory installs
	// resolve to the same path WordPress matches its rewrite rules against.
	$request_path = trim( $request_path, '/' );
	$home_path    = wp_parse_url( home_url(), PHP_URL_PATH );

	if ( is_string( $home_path ) && '' !== $home_path ) {
		$home_path = trim( $home_path, '/' );

		if ( 0 === stripos( $request_path, $home_path ) ) {
			$request_path = trim( substr( $request_path, strlen( $home_path ) ), '/' );
		}
	}

	if ( str_starts_with( $request_path, 'index.php/' ) ) {
		$request_path = substr( $request_path, strlen( 'index.php/' ) );
	}

	// Pretty permalinks carry the route after the REST prefix; anything else is not a REST request.
	if ( ! str_starts_with( $request_path, $rest_prefix ) ) {
		return '';
	}

	return trim( substr( $request_path, strlen( $rest_prefix ) ), '/' );
}