La méthode HTTP QUERY pour les équipes frontend : lectures sécurisées avec un corps de requête
Apprenez quand la méthode HTTP QUERY est préférable à GET et POST pour des filtres complexes, comment l’utiliser avec fetch, ainsi que quels sont les besoins en matière de CORS, de mise en cache et de support infrastructurel.
Les écrans de recherche et de filtrage présentent un problème récurrent lié à l’API. Si l’on encode chaque filtre dans une chaîne de requête GET, l’URL devient longue et peu pratique ; si l’on envoie les filtres sous forme de JSON via une requête POST, on utilise une méthode conçue pour signaler un changement d’état alors que l’opération est en réalité de lecture. La méthode HTTP QUERY a été conçue précisément pour combler cette lacune. Cet article explique ce que signifie QUERY, comment l’utiliser depuis une application React avec fetch, et quels éléments de votre stack, allant du CORS aux caches, nécessitent une attention particulière avant de pouvoir s’en servir.
Le problème que QUERY résout
Une liste de produits avec quelques filtres génère rapidement une requête du type suivant :
/products?category=laptop&brand=Apple&minPrice=50000&maxPrice=150000&rating=4
Cela fonctionne, mais chaque nouveau filtre allonge la chaîne de requête ; les valeurs imbriquées ou répétées (plusieurs marques, une fourchette de prix, un ordre de tri, la pagination) exigent des conventions d’encodage spécifiques, et les URLs très longues peuvent rencontrer des limites de longueur sur les serveurs, les proxies et les journaux.
La solution habituelle est l’utilisation de POST avec un corps JSON. Cela permet une implémentation plus simple du côté client, mais cela complique la définition des contrats. POST n’est ni sûr ni idempotent : les intermédiaires ne peuvent pas supposer que la requête est inoffensive pour être répétée, les caches ne stockeront pas par défaut la réponse, et quiconque consulte l’API doit consulter la documentation pour savoir que ce POST en particulier ne sert qu’à lire des données.
Qu’est-ce que QUERY ?
QUERY est une méthode HTTP permettant de demander à un serveur d’exécuter une requête décrite dans le contenu de la demande. Selon les informations disponibles au moment de la rédaction, l’IETF l’a publiée en tant que standard en juin 2026 sous la référence RFC 10008 ; vérifiez son statut actuel dans l’index des RFC avant de la citer. Au lieu d’intégrer les paramètres dans l’URL, le client les envoie dans le corps de la requête :
QUERY /products HTTP/1.1
Content-Type: application/json
{
"category": "laptop",
"brands": ["Apple", "Dell"],
"price": {
"min": 50000,
"max": 150000
}
}
Le serveur évalue la requête et renvoie les résultats correspondants. Ce qui distingue QUERY de POST, c’est sa sémantique : elle est définie comme sécurisée, ce qui signifie qu’elle ne modifie pas la ressource cible, et idempotente, ce qui signifie que l’envoi deux fois a le même effet que l’envoi une seule fois. Ces deux propriétés permettent aux clients, aux proxies et aux caches de la traiter comme une opération de lecture. L’idempotence, par exemple, signifie qu’un client ou un intermédiaire peut réessayer automatiquement une requête QUERY qui a échoué, sans risquer d’effets secondaires dupliqués, ce qu’il ne devrait pas faire pour une requête POST.
Choix entre GET, POST et QUERY
QUERY ne remplace pas les autres méthodes. Chacune conserve un rôle bien défini :
- GET reste la méthode par défaut pour des récupérations simples : une ressource par identifiant, ou une courte liste avec quelques paramètres basiques.
Pour le frontend, l’avantage réside dans le fait que les états de filtre complexes se traduisent directement en un corps de requête, et le contrat API indique clairement qu’aucun changement n’est effectué.
Envoi d’une requête QUERY depuis React
Imaginons un composant React qui conserve ses filtres de produits actuels dans un objet :
const filters = {
category: "laptop",
brands: ["Apple", "Dell"],
price: {
min: 50000,
max: 150000
},
rating: 4
};
Avec QUERY, cet objet peut être serialisé et envoyé tel quel. L’outil ci-dessous utilise fetch avec un nom de méthode personnalisé et un corps en JSON :
const searchProducts = async (filters) => {
const response = await fetch("/api/products", {
method: "QUERY",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(filters)
});
La seconde partie de cette même fonction vérifie l’état de réponse et analyse le résultat :
if (!response.ok) {
throw new Error("Failed to fetch products");
} return response.json();
};
À part la chaîne de méthode, ceci est identique à une requête POST. Le changement est sémantique et non syntaxique : la requête se déclare désormais comme une requête de type QUERY. Notez deux détails pratiques : la norme Fetch ne majuscule que quelques noms de méthodes bien connus, il faut donc toujours écrire "QUERY" en majuscules. De plus, contrairement à GET et HEAD que fetch refuse d’envoyer avec un corps, QUERY est autorisé à en contenir un.
Un compromis concerne spécifiquement les interfaces utilisateur. Les filtres codés dans l’URL peuvent être enregistrés comme favoris, partagés et survivent au rechargement de la page. Un corps QUERY ne le fait pas. Si les liens partageables sont importants, vous pouvez tout de même vouloir refléter l’état du filtre dans l’URL de la page côté client, tout en envoyant la requête structurée à l’API.
Vérifier la compatibilité sur l’ensemble du chemin de requête
Le fait qu’une méthode soit en cours de standardisation ne signifie pas que tous les composants qui traitent votre trafic la comprennent. Une demande du navigateur traverse plusieurs couches avant d’atteindre l’application, et n’importe laquelle d’entre elles peut rejeter ou altérer une méthode inconnue. Avant de déployer QUERY, vérifiez :
- Le comportement du navigateur et de
fetch()dans les navigateurs que vous prenez en charge. - La configuration CORS de l’API.
- Les passerelles API et les proxies inversés.
- Les CDN et les caches edge.
- Le middleware d’authentification et d’autorisation.
- Les outils de surveillance, d’journalisation et de traçage.
- Le routage et l’analyse du corps des requêtes par le framework backend.
Certaines couches ne permettent qu’une liste fixe de méthodes, et d’autres peuvent ignorer le corps des requêtes pour les méthodes qu’elles ne reconnaissent pas. Testez en conditions réelles dans un environnement similaire à celui de production, et non seulement sur un serveur local.
CORS exige toujours une requête préalable
QUERY n’est pas l’un des méthodes autorisées par CORS (GET, HEAD et POST). Cela signifie qu’une requête QUERY entre origines différentes depuis le navigateur déclenche toujours une requête de prévuelo : avant la vraie requête, le navigateur envoie une requête OPTIONS pour savoir si QUERY est autorisée.
Si votre application React et votre API se trouvent sur des origines différentes, le serveur doit répondre à cette requête de prévuelo avec une en-tête Access-Control-Allow-Methods incluant QUERY, ainsi que tous les en-têtes utilisés par votre requête, tels que Content-Type. Un corps JSON force également déjà une requête de prévuelo pour POST, donc le coût supplémentaire est souvent négligeable, mais la méthode doit être listée explicitement.
Cela peut facilement être oublié pendant le développement. Des outils tels que Postman et curl ne respectent pas les règles CORS, ce qui peut faire en sorte qu’un point de terminaison fonctionne parfaitement dans ces outils mais échoue dans le navigateur.
Le cacheage est possible mais plus complexe
Les réponses aux requêtes QUERY peuvent être mises en cache, ce qui constitue l’un des principaux avantages de cette méthode par rapport à POST. La complication réside dans le fait que la réponse dépend du corps de la requête, et non seulement de l’URL. Prenons en compte ces deux corps de requête envoyés vers le même point d’entrée :
{
"brand": "Apple"
}
{
"brand": "Dell"
}
Ils doivent retourner des résultats différents. Par conséquent, le cache doit inclure le contenu de la requête, ainsi que son type de média, dans la clé de cache afin de déterminer si une réponse stockée peut être réutilisée. Les caches peuvent également normaliser le contenu (par exemple, en ignorant les espaces blancs insignifiants dans le JSON) afin que des requêtes équivalentes partagent une même entrée.
Pour les développeurs React et Next.js, la leçon est de ne pas considérer QUERY comme un « GET avec un corps » en ce qui concerne le caching. Les caches HTTP des navigateurs, les CDN et les caches fetch au niveau du framework ne prennent pas nécessairement en compte le corps de la requête comme clé, il convient donc de vérifier le comportement de chaque couche plutôt que d’assumer des accès au cache réussis.
Comment QUERY est lié à GraphQL
GraphQL est souvent évoqué dans le même contexte, mais les deux fonctionnent à des niveaux différents. GraphQL vous fournit un langage pour décrire les données que vous souhaitez obtenir ainsi qu’un modèle pour les récupérer. QUERY n’est qu’un verbe au niveau du transport : il définit la manière dont une requête contenant un contenu de query doit être traitée par HTTP. Aujourd’hui, les clients GraphQL envoient généralement des opérations via POST ; un serveur GraphQL pourrait en principe accepter des opérations de lecture via QUERY, mais QUERY ne remplace pas GraphQL, et les deux peuvent coexister en fonction de la conception de l’API.
Faut-il migrer les API existantes ?
Généralement non, du moins pas uniquement parce que QUERY existe. Si une extrémité de recherche fonctionne déjà bien via GET ou POST, la changer entraînerait des travaux de migration et de compatibilité pour un bénéfice limité. QUERY est le plus pertinent lors de la conception d’une nouvelle extrémité dont les requêtes sont :
- Uniquement de lecture.
Ce choix offre aux équipes une alternative fondée pour recourir à POST lorsque les requêtes GET deviennent trop complexes à gérer.
Points clés
- Utilisez GET pour les récupérations simples et gardez les appels simples tels quels.
- Envisagez QUERY pour les requêtes complexes et en lecture seule qui nécessitent un corps structuré.
- Ne vous attendez pas à une accélération : QUERY modifie la manière dont la requête est représentée, non la vitesse du backend ou du réseau.
- Vérifiez le support dans les navigateurs, proxies, passerelles, CDN et votre framework backend avant utilisation en production.
- Configurez CORS pour autoriser explicitement cette méthode, et testez dans un vrai navigateur.
- Vérifiez que toutes les clés des couches de cache présentes dans le corps de la requête sont correctes avant de vous fier aux réponses QUERY en mémoire.
- Suivez l’adoption dans l’écosystème : les pages de recherche, les tableaux de bord et les applications gourmandes en données sont ceux où QUERY devrait apporter des résultats rapidement.