Существует ли что-то вроде is_rest ()

18

Я начинаю немного с REST API. Если я не полностью введен в заблуждение, initловушка действия также выполняется, когда это запрос API REST. Теперь я хочу выполнить только некоторый код, когда это не запрос REST API.

Поэтому я искал команду, как is_rest(), чтобы сделать что-то вроде

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

Но я не мог найти что-то подобное. Есть ли is_rest()там?

websupporter
источник
1
Может быть, вы можете уточнить, что вы хотите сделать, когда это не REST-запрос? Тип запроса не определен до синтаксического анализа запроса, что происходит после init. Также обратите внимание, что части API могут использоваться для внутренних запросов, которые не являются запросами REST, поэтому вы рискуете что-то сломать, если полагаетесь на это обнаружение.
Мило
Большое спасибо вам обоим. @birgire: Можете ли вы опубликовать это как ответ, чтобы я мог проверить это. По сути, это ответ на мой вопрос :)
websupporter

Ответы:

14

Это хорошая точка зрения @Milo, REST_REQUESTконстанта определяется как true, rest_api_loaded()если if $GLOBALS['wp']->query_vars['rest_route']не пусто.

Он зацепил в parse_requestчерез:

add_action( 'parse_request', 'rest_api_loaded' );

но parse_requestсрабатывает позже, чем init- см., например, Кодекс здесь .

Было предложение (Даниэль Bachhuber) в билетных # 34373 относительно WP_Query::is_rest(), но он был отложен / отменены.

birgire
источник
11

Просто наткнулся на ту же проблему и написал простую функцию, is_restкоторая позволяет проверить, является ли текущий запрос запросом API REST WP.

<?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;
    }
}

Ссылки:

Матиас Гюнтер
источник
4

Чтобы решить эту проблему, я написал простую пользовательскую функцию, основанную на предположении, что если запрашиваемый URI попадает под URL-адрес Rest API сайта WordPress, то из этого следует, что это запрос Rest API.

Является ли это действительной конечной точкой или аутентифицированной, не для этой функции, чтобы определить. Вопрос в следующем: является ли URL потенциальным URL API отдыха?

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;
}

Если ваш номер $_SERVER['REQUEST_URI']заполнен неправильно, эта функция все равно вернется false.

Нет жесткого кодирования URL, поэтому если вы по какой-то причине измените свою базу URL API, это будет адаптировано.

Пол Г.
источник
3

Может быть не правильно, но я в конечном итоге

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

Не стесняйтесь, дайте мне знать, если это не так. Попытка сделать полезный стартовый плагин, чтобы в конечном итоге поделиться: https://gitlab.com/ripp.io/wordpress/plugin-starter

Charly
источник
1
Я думаю, что это потерпит неудачу, если у вас не будет активных постоянных ссылок.
websupporter
Вы определенно правы
Чарли
Хорошо, это требует довольно постоянной ссылки ... но кто не хочет этого? Это кажется мне самым безопасным способом сделать это. Все другие решения причудливы, но со временем, если вы хотите, чтобы ваш код по-прежнему работал на более поздних версиях wp ... это мне кажется безопасным способом !!
Энтони Гиббс
1

Два варианта здесь действительно,

  1. Проверьте, REST_REQUESTопределено ли.
  2. Зацепись за то, rest_api_initкуда ты хотел зацепиться init.
отметка
источник
0

Вот что я придумал:

/**
 * 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;
}

Однако у меня не было много времени, чтобы заставить CLI обнаруживать REST-запросы до того, как сработало parse_requestдействие. Я открыт для предложений!

Я еще не написал несколько тестов для этой функции, я обновлю этот ответ, как только сделаю.

-- Редактировать

Только что нашел, как WooCommerce справляется с этим. WooCommerce не учитывает постоянные ссылки:

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 );
}
Лукас Бустаманте
источник