# Derrière une route REST, le cycle de chargement de WordPress tourne encore

> Une requête vers une route REST déclenche les mêmes hooks du cœur qu'une page rendue classiquement. Comprendre cet ordre aide à déboguer un comportement inattendu.

- Auteur : Clément Hadrot
- Publié le : 2024-06-25
- Mis à jour le : 2024-06-25
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/derriere-route-rest-cycle-chargement-wordpress/

## L’essentiel

- plugins_loaded, init et rest_api_init s'exécutent dans un ordre précis
- Une requête REST charge l'intégralité du cœur, pas seulement le routeur
- Un plugin mal conditionné peut interférer avec une réponse REST sans lien apparent

« Une route REST, c'est plus léger qu'une page complète, non ? » Cette hypothèse, répandue chez les développeurs qui découvrent le développement headless, mérite d'être corrigée : une requête vers `/wp-json/` déclenche le chargement complet du cœur de WordPress, exactement comme le ferait l'affichage d'une page classique. Ce que la route REST évite, c'est uniquement le rendu du gabarit de thème, pas l'initialisation du logiciel dans son ensemble.

Comprendre précisément quels hooks s'exécutent, et dans quel ordre, avant qu'une réponse REST ne soit renvoyée permet de déboguer efficacement un comportement inattendu : un champ manquant, une donnée non filtrée comme prévu, ou une extension qui semble interférer sans lien apparent avec la route concernée.

## L'ordre réel d'exécution

Une requête HTTP vers une route de l'API REST traverse la même séquence d'amorçage que n'importe quelle autre requête WordPress, avec quelques hooks spécifiques qui s'ajoutent en cours de route :

1. `plugins_loaded` : toutes les extensions actives sont chargées, y compris celles sans lien apparent avec l'API REST.
2. `init` : les types de contenus personnalisés, les taxonomies et les routes REST elles-mêmes sont enregistrés via `register_post_type()` et consorts.
3. `rest_api_init` : ce hook spécifique se déclenche uniquement lorsque la requête entrante cible effectivement l'API REST, et sert de point d'ancrage privilégié pour `register_rest_route()`.
4. Résolution de la route, exécution du `permission_callback`, puis du callback principal.

> L'essentiel à retenir : plugins_loaded, init et rest_api_init s'exécutent dans un ordre précis ; Une requête REST charge l'intégralité du cœur, pas seulement le routeur ; Un plugin mal conditionné peut interférer avec une réponse REST sans lien apparent

## Ce que cet ordre explique concrètement

### Un filtre appliqué deux fois sans raison apparente

Un développeur qui accroche un filtre `the_content` à la fois dans le rendu classique et dans le traitement d'une route REST personnalisée peut observer une transformation appliquée deux fois si le callback de la route appelle indirectement une fonction qui exécute déjà ce filtre, comme `get_the_content()` suivi d'un traitement manuel équivalent. Comprendre que `init` précède l'exécution du callback de route aide à localiser où ce filtre a réellement été accroché et pourquoi il s'applique dans ce contexte précis.

### Une extension qui modifie une réponse REST sans y toucher directement

Une extension de sécurité activée sur le site, qui bloque certaines requêtes selon leur en-tête `User-Agent` dès le hook `init`, peut empêcher une route REST légitime de répondre correctement, alors que rien dans le code de cette route ne semble concerné. Le fait que `plugins_loaded` et `init` s'exécutent avant même que la route ne soit identifiée explique pourquoi ce type d'interférence, en apparence sans rapport, doit systématiquement figurer dans la liste des causes à vérifier.

## Utiliser cet ordre pour déboguer efficacement

Ajouter des points de trace à chaque étape clé du cycle permet de confirmer précisément où un comportement diverge de l'attendu :

```
add_action( 'plugins_loaded', function () {
    error_log( 'plugins_loaded : ' . $_SERVER['REQUEST_URI'] );
} );

add_action( 'rest_api_init', function () {
    error_log( 'rest_api_init declenche' );
} );

add_filter( 'rest_pre_dispatch', function ( $result, $server, $request ) {
    error_log( 'route resolue : ' . $request->get_route() );
    return $result;
}, 10, 3 );
```

Cette instrumentation temporaire, à retirer une fois le diagnostic posé, révèle rapidement si un plugin tiers interfère avant même que la route personnalisée n'entre en jeu, un cas fréquent quand plusieurs extensions de sécurité ou de cache coexistent sur la même installation.

## Ce que cela signifie pour la conception

- Une route REST ne dispense jamais d'auditer l'ensemble des extensions actives sur l'installation, même sans lien apparent avec l'API.
- Le hook `rest_api_init` reste le point d'ancrage le plus fiable pour enregistrer des routes personnalisées, plutôt que `init` seul.
- Un comportement inattendu sur une route REST mérite d'être vérifié en remontant tout le cycle, pas seulement le code du callback lui-même.

> Une route REST qui répond en apparence de façon isolée reste, sous le capot, un point d'arrivée d'un cycle de chargement complet. Ignorer ce cycle en cas de comportement anormal revient à chercher une clé perdue uniquement sous le lampadaire, là où la lumière est la plus commode.

## En résumé

La légèreté apparente d'une réponse REST ne doit pas masquer la réalité de son exécution : le cœur de WordPress tourne intégralement derrière chaque requête, avec ses hooks, ses extensions actives et ses filtres. Garder cet ordre précis en tête simplifie considérablement le débogage d'un comportement qui semble, à première vue, n'avoir aucun lien avec la route concernée.
