Le client HTTP de JetBrains : testez vos API sans quitter votre IDE
Quand on développe une API, le réflexe classique, c’est d’ouvrir Postman, ou plus récemment Bruno, pour envoyer quelques requêtes et vérifier que tout fonctionne. Ça marche, mais ça implique un changement de contexte permanent. On code dans PhpStorm, on alt-tab vers Postman, on revient, on re-tab…
Vous ne savez peut-être pas que tous les IDE JetBrains (PhpStorm, IntelliJ, WebStorm, GoLand…) embarquent un client HTTP complet, directement dans l’éditeur. Des fichiers .http versionnés avec le projet, exécutables en un clic, avec variables d’environnement, scripts, support GraphQL et autocomplétion OpenAPI.
Je l’utilise au quotidien depuis plus de deux ans, et je n’ai aucune envie de revenir en arrière.
Les bases : GET, POST et headers
On crée un fichier .http (ou .rest) n’importe où dans le projet. La syntaxe est minimaliste :
### Liste des utilisateursGET http://localhost:8080/api/usersAccept: application/jsonPour un POST avec un body JSON, on ajoute simplement le contenu après une ligne vide :
### Créer un utilisateurPOST http://localhost:8080/api/usersContent-Type: application/json
{ "name": "Nicolas Demay",}Les headers se placent juste après la ligne de requête, sans ligne vide entre eux. Le séparateur ### permet d’enchaîner plusieurs requêtes dans le même fichier et de les nommer pour s’y retrouver.
### AuthentificationPOST http://localhost:8080/api/loginContent-Type: application/json
{ "username": "admin", "password": "secret"}
### Récupérer le profil (requête protégée)GET http://localhost:8080/api/profileAuthorization: Bearer {{auth_token}}Accept: application/jsonOn lance chaque requête individuellement via l’icône play en marge, ou toutes d’un coup. La réponse s’affiche dans un panneau dédié avec le status code, les headers, et le body formaté.
D’ailleurs, petit tips : si vous avez une requête XHR qui pose problème dans le navigateur, clic droit dans les DevTools → “Copy as cURL”, puis collez directement dans un fichier .http. L’IDE convertit le cURL en syntaxe HTTP Client automatiquement. Pas besoin de réécrire les headers à la main.
Variables et environnements
On définit des environnements dans un fichier http-client.env.json, soit à la racine du projet, soit dans le même dossier que le fichier .http :
{ "dev": { "host": "http://localhost:8080", "api_version": "v1" }, "staging": { "host": "https://staging.example.com", "api_version": "v1" }, "production": { "host": "https://api.example.com", "api_version": "v2" }}Les secrets vont dans un fichier séparé http-client.private.env.json (à ajouter dans le .gitignore, on a tous déjà pushé un token sur un repo public au moins une fois) :
{ "dev": { "api_token": "dev-token-xxx" }, "staging": { "api_token": "staging-token-yyy" }}Et dans les requêtes, on utilise la syntaxe {{variable}} :
### Liste des produitsGET {{host}}/api/{{api_version}}/productsAuthorization: Bearer {{api_token}}Accept: application/jsonAvant d’exécuter, un dropdown en haut de l’éditeur permet de choisir l’environnement cible. Les valeurs du fichier privé écrasent celles du fichier partagé. Du coup, l’équipe partage les URLs et la structure, chacun garde ses propres tokens.
L’IDE fournit aussi des variables dynamiques prêtes à l’emploi :
### Créer une ressource avec un ID uniquePOST {{host}}/api/itemsContent-Type: application/json
{ "id": "{{$uuid}}", "createdAt": "{{$isoTimestamp}}", "priority": {{$randomInt}}}Pre-request et response handlers
Les response handlers (avec >) s’exécutent après la réponse et permettent de tester des assertions ou de stocker des valeurs :
### Login et stockage du tokenPOST {{host}}/api/loginContent-Type: application/json
{ "username": "admin", "password": "{{password}}"}
> {% client.test("Login réussi", function() { client.assert(response.status === 200, "Status attendu : 200"); }); // Store the token for subsequent requests client.global.set("auth_token", response.body.token);%}Le token est maintenant accessible via {{auth_token}} dans toutes les requêtes suivantes. On peut enchaîner les appels avec des dépendances de données.
Les pre-request scripts (avec <) s’exécutent avant l’envoi et permettent de préparer les données :
< {% // Generate a signature before sending const timestamp = Date.now().toString(); request.variables.set("timestamp", timestamp); request.variables.set("requestId", $random.uuid);%}POST {{host}}/api/secureContent-Type: application/jsonX-Timestamp: {{timestamp}}X-Request-Id: {{requestId}}
{ "data": "payload"}Bref, on a client.log() pour débugger et client.test() pour créer de vraies suites de tests. Rien de révolutionnaire, mais ça fait le boulot sans quitter l’éditeur.
Upload de fichiers
Pour envoyer un fichier dans une requête, on utilise la syntaxe < suivie du chemin :
### Upload simple (body = contenu du fichier)POST {{host}}/api/importContent-Type: application/json
< ./data/import.json
### Upload multipart (formulaire avec fichier)POST {{host}}/api/uploadContent-Type: multipart/form-data; boundary=boundary
--boundaryContent-Disposition: form-data; name="file"; filename="document.pdf"Content-Type: application/pdf
< ./files/document.pdf--boundaryContent-Disposition: form-data; name="description"
Mon fichier uploadé--boundary--Attention : < lit un fichier en entrée (dans le body), > est réservé aux response handlers. Ne pas confondre les deux.
Support GraphQL
Le client HTTP supporte nativement GraphQL avec le mot-clé GRAPHQL :
### QueryGRAPHQL {{host}}/graphql
query { users { id name email }}
### Mutation avec variablesGRAPHQL {{host}}/graphql
mutation ($input: CreateUserInput!) { createUser(input: $input) { id name }}
{ "input": { "name": "Nicolas", }}Et si l’IDE connaît déjà votre API ?
Si le projet contient une spécification OpenAPI (ou si on pointe vers un fichier distant), l’IDE s’en sert pour enrichir les fichiers .http :
- Autocomplétion des URLs : les endpoints définis dans la spec sont suggérés pendant la frappe
- Autocomplétion du body JSON : les champs requis sont proposés automatiquement
Même principe côté GraphQL : il faut installer le plugin GraphQL (gratuit sur le Marketplace JetBrains). Une fois activé, il introspecte le schéma de l’endpoint et propose l’autocomplétion sur les types, les champs et les arguments directement dans le fichier .http.
C’est là que l’avantage sur Postman est le plus net : l’IDE connaît déjà le code et la doc API. Pas d’import manuel, pas de synchronisation à maintenir.
Le vrai gain : le debug en un clic
C’est peut-être l’avantage le moins visible, mais celui qui me fait gagner le plus de temps. Quand on développe une API dans PhpStorm, on peut poser un point d’arrêt Xdebug dans le code, puis relancer la requête HTTP en un seul clic.
Pas besoin de retourner dans le fichier .http à chaque fois. Le bouton play en haut de l’IDE garde en mémoire la dernière commande exécutée — que ce soit un test unitaire ou une requête HTTP. On modifie le code, on pose un breakpoint, on clique sur play, et on est directement dans le debugger avec la bonne requête. Le cycle éditer → tester → débugger tient en quelques secondes, sans changer de fenêtre.
Avec Postman, ce workflow est cassé : il faut alt-tabber, relancer, revenir. Ici, tout reste dans le même écran.
Et avec l’IA dans la boucle ?
Le vrai bonus de ce format, c’est que les fichiers .http vivent dans le repo comme n’importe quel fichier de code. Versionnés, lisibles, partageables. Et du coup, un assistant comme Claude y a accès directement dans le contexte du projet.
En pratique, je lui demande régulièrement de me générer une requête .http pour tester un endpoint que je viens de créer. Il connaît le code, il connaît le schéma — le fichier est prêt en quelques secondes. Essayez de faire ça avec une collection Postman.