Czy istnieje coś takiego jak is_rest ()?

18

Zaczynam trochę z interfejsem API REST. Jeśli nie jestem całkowicie wprowadzony w błąd, initchwytak akcji jest również wykonywany, gdy jest to żądanie interfejsu API REST. Teraz chcę wykonać tylko część kodu, gdy nie jest to żądanie interfejsu API REST.

Więc szukałem polecenia takiego is_rest(), aby zrobić coś takiego

<?php
if( ! is_rest() ) echo 'no-rest-request';
?>

Ale nie mogłem znaleźć czegoś takiego. Czy jest coś takiego is_rest()?

websupporter
źródło
1
Może możesz wyjaśnić, co chcesz zrobić, gdy nie jest to żądanie REST? Typ żądania nie jest określany do momentu parsowania zapytania, co dzieje się później init. Pamiętaj również, że części interfejsu API mogą być używane wewnętrznie w żądaniach, które nie są żądaniami REST, więc ryzykujesz uszkodzenie czegoś, jeśli polegasz na tym wykryciu.
Milo
Dziękuję wam obojgu. @ birgire: Czy możesz to opublikować jako odpowiedź, abym mógł to sprawdzić. Zasadniczo jest to odpowiedź na moje pytanie :)
operator sieci

Odpowiedzi:

14

To dobry punkt @Milo, REST_REQUESTstała jest zdefiniowana jako true, w obrębie rest_api_loaded()jeśli $GLOBALS['wp']->query_vars['rest_route']jest niepuste.

Jest podłączona do parse_requesturządzeń:

add_action( 'parse_request', 'rest_api_loaded' );

ale parse_requeststrzela później niż init- patrz na przykład Kodeks tutaj .

Było sugestia (Daniel Bachhuber) w bilety # 34373 czasowo WP_Query::is_rest(), ale została przełożona / anulowana.

birgire
źródło
# 42061 może dodać wp_is_rest_request()lub wp_doing_rest().
Ian Dunn
11

Natknąłem się na ten sam problem i napisałem prostą funkcję, is_restktóra pozwala sprawdzić, czy bieżące żądanie jest żądaniem API WP REST.

<?php
if ( !function_exists( 'is_rest' ) ) {
    /**
     * Checks if the current request is a WP REST API request.
     *
     * Case #1: After WP_REST_Request initialisation
     * Case #2: Support "plain" permalink settings
     * Case #3: It can happen that WP_Rewrite is not yet initialized,
     *          so do this (wp-settings.php)
     * Case #4: URL Path begins with wp-json/ (your REST prefix)
     *          Also supports WP installations in subfolders
     *
     * @returns boolean
     * @author matzeeable
     */
    function is_rest() {
        $prefix = rest_get_url_prefix( );
        if (defined('REST_REQUEST') && REST_REQUEST // (#1)
                || isset($_GET['rest_route']) // (#2)
                        && strpos( trim( $_GET['rest_route'], '\\/' ), $prefix , 0 ) === 0)
                return true;
        // (#3)
        global $wp_rewrite;
        if ($wp_rewrite === null) $wp_rewrite = new WP_Rewrite();

        // (#4)
        $rest_url = wp_parse_url( trailingslashit( rest_url( ) ) );
        $current_url = wp_parse_url( add_query_arg( array( ) ) );
        return strpos( $current_url['path'], $rest_url['path'], 0 ) === 0;
    }
}

Bibliografia:

Matthias Günter
źródło
4

Aby rozwiązać ten problem, napisałem prostą funkcję niestandardową opartą na założeniu, że jeśli żądany identyfikator URI mieści się pod adresem URL interfejsu API Rest witryny WordPress, oznacza to, że jest to żądanie interfejsu API Rest.

Ta funkcja nie określa, czy jest to prawidłowy punkt końcowy, czy jest uwierzytelniony. Pytanie brzmi: czy adres URL jest potencjalnym adresem URL interfejsu API usługi Rest?

function isRestUrl() {
    $bIsRest = false;
    if ( function_exists( 'rest_url' ) && !empty( $_SERVER[ 'REQUEST_URI' ] ) ) {
        $sRestUrlBase = get_rest_url( get_current_blog_id(), '/' );
        $sRestPath = trim( parse_url( $sRestUrlBase, PHP_URL_PATH ), '/' );
        $sRequestPath = trim( $_SERVER[ 'REQUEST_URI' ], '/' );
        $bIsRest = ( strpos( $sRequestPath, $sRestPath ) === 0 );
    }
    return $bIsRest;
}

Jeśli twoje pole $_SERVER['REQUEST_URI']nie jest odpowiednio wypełnione, funkcja ta powróci false, niezależnie od tego.

Adres URL nie jest kodowany na stałe, więc jeśli z jakiegoś powodu zmienisz bazę URL interfejsu API, dostosuje się on.

Paul G.
źródło
3

Może nie w porządku, ale skończyło się

if (strpos($_SERVER[ 'REQUEST_URI' ], '/wp-json/') !== false) {
    // Cool API stuff here
}

Daj mi znać, jeśli to nie w porządku. Próba stworzenia pomocnego startera dla wtyczek, aby w końcu udostępnić: https://gitlab.com/ripp.io/wordpress/plugin-starter

Charly
źródło
1
Myślę, że to by się nie powiodło, gdybyś nie miał aktywnych aktywnych łączy bezpośrednich.
websupporter
Masz zdecydowanie rację
Charly
Ok, to wymaga bezpośredniego połączenia ... ale kto tego nie chce !!!? To wydaje mi się najbezpieczniejszym sposobem na zrobienie tego. Wszystkie inne rozwiązania są fantazyjne, ale z czasem, jeśli chcesz, aby Twój kod nadal działał w późniejszych wersjach wp ... wydaje mi się to bezpieczny sposób !!
Antony Gibbs
1

Dwie opcje tutaj naprawdę,

  1. Sprawdź, czy REST_REQUESTjest zdefiniowane.
  2. Zaczep w rest_api_initmiejscu, w którym chciałeś się zaczepić init.
znak
źródło
0

Oto, co wymyśliłem:

/**
 * Determines if the current request we are handling is a REST Request.
 * This function can be called even on mu-plugins.
 *
 * You might want to prefix this function name with
 * something more unique to your project.
 *
 * @return bool
 */
function is_rest(): bool {
    $is_cli              = php_sapi_name() === 'cli';
    $permalink_structure = get_option( 'permalink_structure' );
    $rest_prefix         = rest_get_url_prefix();

    if ( ! empty( $permalink_structure ) && ! $is_cli ) {
        /*
         * HTTP request with Pretty Permalinks.
         */
        if ( substr( $_SERVER['REQUEST_URI'], 0, strlen( $rest_prefix ) ) === $rest_prefix ) {
            return true;
        }
    } elseif ( empty( $permalink_structure ) && ! $is_cli ) {
        /*
         * HTTP Requests with Plain Permalinks
         *
         * We can rely on "?rest_route" for plain permalinks, this value don't change:
         * wp/wp-includes/rest-api.php:145
         *
         * All ?rest_route must start with "/":
         * wp/wp-includes/rest-api.php:159
         */
        if ( isset( $_GET['rest_route'] ) && substr( $_GET['rest_route'], 0, 1 ) === '/' ) {
            return true;
        }
    } elseif ( $is_cli ) {
        /*
         * CLI request
         */
        if ( did_action( 'parse_request' ) ) {
            return defined( 'REST_REQUEST' ) && REST_REQUEST;
        } else {
            throw new RuntimeException( "Maybe someone at StackOverflow can help fill this gap of identifying REST requests on CLI before the parse_request action has fired and the REST_REQUEST constant is available?" );
        }
    }

    return false;
}

parse_requestJednak nie miałem zbyt wiele czasu na zastanowienie się, czy CLI wykrywa żądania REST przed uruchomieniem akcji. Jestem otwarty na sugestie!

Mam jeszcze napisać kilka testów dotyczących tej funkcji, zaktualizuję tę odpowiedź, kiedy to zrobię.

-- Edytować

Właśnie odkryłem, jak WooCommerce sobie z tym radzi. WooCommerce nie wydaje się uwzględniać zwykłych bezpośrednich linków:

public function is_rest_api_request() {
    if ( empty( $_SERVER['REQUEST_URI'] ) ) {
        return false;
    }

    $rest_prefix         = trailingslashit( rest_get_url_prefix() );
    $is_rest_api_request = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix ) );

    return apply_filters( 'woocommerce_is_rest_api_request', $is_rest_api_request );
}
Lucas Bustamante
źródło