¿Existe algo como is_rest ()

18

Estoy empezando un poco con la API REST. Si no estoy completamente engañado, el initenlace de acción también se ejecuta cuando se trata de una solicitud REST API. Ahora, quiero ejecutar solo un código, cuando no es una solicitud REST API.

Entonces estaba buscando un comando como is_rest()para hacer algo como

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

Pero no pude encontrar algo como esto. ¿Hay un is_rest()por ahí?

soporte web
fuente
1
¿Quizás pueda explicar qué quiere hacer cuando no se trata de una solicitud REST? El tipo de solicitud no se determina hasta el análisis de la consulta, que ocurre después init. También tenga en cuenta que las partes de la API pueden usarse internamente en solicitudes que no son solicitudes REST, por lo que se arriesga a romper algo si confía en esa detección.
Milo
Muchas gracias a los dos. @birgire: ¿Puedes publicar esto como respuesta para que pueda verificarlo? Básicamente, es la respuesta a mi pregunta :)
websupporter

Respuestas:

14

Es un buen punto de @Milo, la REST_REQUESTconstante se define como true, dentro de rest_api_loaded()si $GLOBALS['wp']->query_vars['rest_route']no está vacía.

Está conectado a parse_requesttravés de:

add_action( 'parse_request', 'rest_api_loaded' );

pero se parse_requestdispara más tarde que init: vea, por ejemplo, el Codex aquí .

Hubo una sugerencia (por Daniel Bachhuber) en el boleto # 34373 con respecto WP_Query::is_rest(), pero fue pospuesta / cancelada.

Birgire
fuente
11

Simplemente tropecé con el mismo problema y escribí una función simple is_restque le permite verificar si la solicitud actual es una solicitud WP REST API.

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

Referencias

Matthias Günter
fuente
4

Para resolver este problema, escribí una función personalizada simple basada en el supuesto de que si el URI que se solicita cae dentro de la URL de la API Rest del sitio de WordPress, entonces se deduce que es una solicitud de la API Rest.

Si se trata de un punto final válido o autenticado, no es para que esta función lo determine. La pregunta es esta: ¿es la URL una posible URL de Rest 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;
}

Si $_SERVER['REQUEST_URI']no está correctamente poblado, esta función seguirá regresando false, independientemente.

No hay una codificación rígida de la URL, por lo que si por alguna razón cambia su base de URL de API, esto se adaptará.

Paul G.
fuente
3

Tal vez no está bien, pero terminé con

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

No dudes en avisarme si esto no está bien. Intentando hacer un útil complemento de inicio para finalmente compartir: https://gitlab.com/ripp.io/wordpress/plugin-starter

Charly
fuente
1
Creo que esto fallaría si no tuviera activos enlaces permanentes.
websupporter
Definitivamente tienes razón
Charly
Ok, requiere bastante enlace permanente ... pero ¿quién no lo quiere? Esta me parece la forma más segura de hacer esto. Todas las demás soluciones son sofisticadas, pero con el tiempo, si desea que su código aún se ejecute en versiones posteriores de wp ... ¡esto me parece una forma segura!
Antony Gibbs
1

Dos opciones aquí realmente,

  1. Verifique si REST_REQUESTestá definido.
  2. Conéctate a rest_api_initdonde querías engancharte init.
marca
fuente
0

Esto es lo que se me ocurrió:

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

Sin parse_requestembargo, no he tenido mucho tiempo para hacer que CLI detecte las solicitudes REST antes de que la acción se active. Estoy abierto a sugerencias!

Todavía tengo que escribir algunas pruebas sobre esta característica, actualizaré esta respuesta una vez que lo haga.

- Editar

Acabo de descubrir cómo WooCommerce maneja esto. WooCommerce no parece tener en cuenta los enlaces permanentes 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
fuente