Existe algo como is_rest ()

16

Estou começando um pouco com a API REST. Se eu não sou completamente enganado, o initgancho de ação também é executado quando é uma solicitação da API REST. Agora, desejo executar apenas um código, quando não for uma solicitação da API REST.

Então, eu estava procurando por um comando como is_rest()para fazer algo como

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

Mas não consegui encontrar algo assim. Existe um is_rest()lá fora?

websupporter
fonte
1
Talvez você possa detalhar o que deseja fazer quando não é uma solicitação REST? O tipo de solicitação não é determinado até a análise da consulta, que ocorre depois init. Observe também que as partes da API podem ser usadas internamente em solicitações que não são solicitações REST; portanto, você corre o risco de quebrar algo se confiar nessa detecção.
Milo
Muito obrigado a vocês dois. @ Birgire: Você pode postar isso como uma resposta, para que eu possa verificar. Basicamente, é a resposta para a minha pergunta :) #
6878

Respostas:

14

É um bom argumento do @Milo, a REST_REQUESTconstante é definida como true, dentro de rest_api_loaded()se $GLOBALS['wp']->query_vars['rest_route']não estiver vazia.

Está ligado à parse_requestvia:

add_action( 'parse_request', 'rest_api_loaded' );

mas é parse_requestacionado depois de init- Veja, por exemplo, o Codex aqui .

Houve uma sugestão (por Daniel Bachhuber) em ticket # 34373 respeito WP_Query::is_rest(), mas foi adiado / cancelada.

Birgire
fonte
11

Apenas tropeçou no mesmo problema e escreveu uma função simples is_restque permite verificar se a solicitação atual é uma solicitação da 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;
    }
}

Referências:

Matthias Günter
fonte
4

Para resolver esse problema, escrevi uma função personalizada simples com base no pressuposto de que, se o URI sendo solicitado se enquadra na URL da API Rest do site WordPress, segue-se que é uma solicitação da API Rest.

Se é um ponto de extremidade válido ou autenticado, não é para esta função determinar. A questão é a seguinte: o URL é um URL potencial da API 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;
}

Se você $_SERVER['REQUEST_URI']não estiver preenchido corretamente, essa função ainda retornará false, independentemente.

Não há codificação codificada do URL. Se, por algum motivo, você alterar sua base de URL da API, isso será adaptado.

Paul G.
fonte
3

Talvez não esteja certo, mas acabei com

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

Sinta-se à vontade para me informar se isso não estiver certo. Tentando criar um iniciador de plug-in útil para eventualmente compartilhar: https://gitlab.com/ripp.io/wordpress/plugin-starter

Charly
fonte
1
Eu acho que isso falharia, se você não tivesse permalinks bastante ativos.
Websupporter
Você está definitivamente correto
Charly
Ok, requer bastante permalink ... mas quem não quer !!!? Esta me parece a maneira mais segura de fazer isso. Todas as outras soluções são sofisticadas, mas com o tempo, se você quiser que seu código ainda seja executado em versões posteriores do wp ... isso me parece uma maneira segura!
Antony Gibbs
1

Duas opções aqui realmente,

  1. Verifique se REST_REQUESTestá definido.
  2. Conecte-se ao rest_api_initlocal em que deseja conectar init.
Marca
fonte
0

Aqui está o que eu vim com:

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

No parse_requestentanto, não tive muito tempo para fazer com que a CLI detecte solicitações REST antes que a ação seja acionada. Estou aberto a sugestões!

Ainda estou para escrever alguns testes sobre esse recurso, atualizarei esta resposta assim que o fizer.

- Editar

Acabei de descobrir como o WooCommerce lida com isso. O WooCommerce parece não dar conta de permalinks simples:

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
fonte