check the requesting url

That filter is definitely not the one you are looking for. That filter fires before returning the result of WP_REST_Request::from_url() which appears to be a factory method that is only used internally to handle embeds.

A better option is to return a WP_Error instance on the rest_pre_dispatch filter.

Some caveats:

As mentioned by @milo, the referer is not reliable and shouldn’t be used for a security check.

Additionally, it is not guaranteed to be set.

With those out of the way, here is an example of how you might use the rest_pre_dispatch filter to cause the request to fail if it is from a bad referer:

function wpse281916_rest_check_referer( $result, $server, $request ) {
    if ( null !== $result ) {
        // Core starts with a null value.
        // If it is no longer null, another callback has claimed this request.
        // Up to you how to handle - for this example we will just return early.
        return $result;
    }

    $referer = $request->get_header( 'referer' );

    if ( ! $referer ) {
        // Referer header is not set - If referer is required, return a WP_Error instance instead.
        return $result;
    }

    $host = wp_parse_url( $referer, PHP_URL_HOST );

    if ( ! $host ) {
        // Referer is malformed - If referer is required, return a WP_Error instance instead.
        return $result;
    }

    if ( 'mysite.com' !== $host ) {
        // Referer is set to something that we don't allow.
        return new WP_Error(
            'invalid-referer',
            'Requests must contain a valid referer',
            compact( 'referer' )
        );
    }

    // Otherwise we are good - return original result and let WordPress handle as usual.
    return $result;
}
add_filter( 'rest_pre_dispatch', 'wpse281916_rest_check_referer', 10, 3 );

Leave a Comment