Esiste qualcosa come is_rest() in WordPress?
Sto iniziando a lavorare un po' con le REST API. Se non mi sbaglio completamente, l'hook di azione init
viene eseguito anche quando si tratta di una richiesta REST API. Ora voglio eseguire del codice solo quando non si tratta di una richiesta REST API.
Quindi stavo cercando un comando come is_rest()
per fare qualcosa del tipo:
<?php
if( ! is_rest() ) echo 'no-rest-request';
?>
Ma non ho trovato niente del genere. Esiste una funzione is_rest()
?

È un'ottima osservazione quella di @Milo, la costante REST_REQUEST
è definita come true
all'interno di rest_api_loaded()
se $GLOBALS['wp']->query_vars['rest_route']
non è vuoto.
Viene agganciata a parse_request
tramite:
add_action( 'parse_request', 'rest_api_loaded' );
ma parse_request
viene attivato dopo init
- Vedi ad esempio il Codex qui.
C'era stata una proposta (di Daniel Bachhuber) nel ticket #34373 riguardo a WP_Query::is_rest()
, ma è stata rinviata/annullata.

#42061 potrebbe aggiungere wp_is_rest_request()
o wp_doing_rest()
.

Mi sono appena imbattuto nello stesso problema e ho scritto una semplice funzione is_rest
che ti permette di verificare se la richiesta corrente è una richiesta dell'API REST di WordPress.
<?php
if ( !function_exists( 'is_rest' ) ) {
/**
* Verifica se la richiesta corrente è una richiesta dell'API REST di WordPress.
*
* Caso #1: Dopo l'inizializzazione di WP_REST_Request
* Caso #2: Supporta le impostazioni di permalink "semplici" e verifica se `rest_route` inizia con `/`
* Caso #3: Può succedere che WP_Rewrite non sia ancora inizializzato,
* quindi esegui questo (wp-settings.php)
* Caso #4: Il percorso URL inizia con wp-json/ (il tuo prefisso REST)
* Supporta anche installazioni WP in sottocartelle
*
* @returns boolean
* @author matzeeable
*/
function is_rest() {
if (defined('REST_REQUEST') && REST_REQUEST // (#1)
|| isset($_GET['rest_route']) // (#2)
&& strpos( $_GET['rest_route'], '/', 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;
}
}
Riferimenti:

Questa è la migliore funzione per WordPress mai scritta su stackoverflow. Avevo bisogno di usarla per un hook pre_get_posts
che ignora le richieste REST e ha funzionato alla perfezione.

Se ti serve dopo che init
è stato eseguito:
defined('REST_REQUEST') && REST_REQUEST
Se ti serve prima di init
, ci sono due modi:
Usa wp_is_json_request()
(introdotto in WordPress 5.0), o cerca di dedurre se è una richiesta REST attraverso l'URL. Rilevare l'URL varierà a seconda che il sito utilizzi permalink o permalink semplici.
WooCommerce lo fa in questo modo, ed è una buona soluzione:
function is_rest_api_request() {
if ( empty( $_SERVER['REQUEST_URI'] ) ) {
// Probabilmente una richiesta CLI
return false;
}
$rest_prefix = trailingslashit( rest_get_url_prefix() );
$is_rest_api_request = strpos( $_SERVER['REQUEST_URI'], $rest_prefix ) !== false;
return apply_filters( 'is_rest_api_request', $is_rest_api_request );
}

Due opzioni qui, in realtà,
- Controlla se
REST_REQUEST
è definito. - Agganciati a
rest_api_init
dove volevi agganciarti ainit
.

Per risolvere questo problema ho scritto una semplice funzione personalizzata basata sull'assunto che se l'URI richiesto rientra nell'URL dell'API REST del sito WordPress, allora si tratta di una richiesta all'API REST.
Se si tratti di un endpoint valido o autenticato, non spetta a questa funzione determinarlo. La domanda è: l'URL è un potenziale URL dell'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 il tuo $_SERVER['REQUEST_URI']
non è popolato correttamente, questa funzione restituirà comunque false
.
Non c'è alcun hard-coding dell'URL, quindi se per qualche motivo cambi la base dell'URL dell'API, questa funzione si adatterà automaticamente.

Forse non è corretto, ma ho finito con
if (strpos($_SERVER[ 'REQUEST_URI' ], '/wp-json/') !== false) {
// Roba interessante per l'API qui
}
Sentiti libero di farmi sapere se questo non è corretto. Sto cercando di creare uno starter utile per plugin da condividere eventualmente: https://gitlab.com/ripp.io/wordpress/plugin-starter

Penso che questo fallirebbe, se non avessi i pretty permalink attivi.

Ok richiede i pretty permalink... ma chi non li vorrebbe!!!? Questa mi sembra la soluzione più sicura per farlo. Tutte le altre soluzioni sono fantasiose ma col tempo se vuoi che il tuo codice continui a funzionare sulle versioni successive di wp... questa mi sembra la strada più sicura!!

Con WordPress 6.5, il core fornisce una funzione come wp_is_rest_endpoint
per determinare in modo affidabile se la richiesta corrente è una richiesta verso un endpoint REST.
C'è anche un'altra funzione wp_is_serving_rest_request
per verificare se una richiesta REST API è effettivamente in fase di elaborazione. Se la usi, assicurati di chiamarla dopo l'azione parse_request
, poiché restituirà sempre false
prima di essa.

Puoi utilizzare wp_is_json_request()
come mostrato di seguito:
if ( wp_is_json_request() ) {
// esegui qui le tue operazioni
}
Assicurati di impostare Accepts
o Content-Type
come application/json
altrimenti wp_is_json_request()
restituirà false.
Ulteriore documentazione: https://developer.wordpress.org/reference/functions/wp_is_json_request/
