Le test des API localhost qui doivent recevoir des webhooks ou des rappels de services externes nécessite d'exposer temporairement votre serveur de développement local à Internet. Des services de tunneling comme ngrok, NPort, Cloudflare Tunnel et d'autres créent des connexions sécurisées qui attribuent une URL publique à votre localhost.
Pourquoi vous avez besoin du tunneling de localhost
Vous construisez une API qui s'intègre à des services tiers. Tout fonctionne sur votre ordinateur portable — les points de terminaison répondent correctement, les données circulent sans problème. Ensuite, vous essayez de tester les rappels de webhook de Stripe, GitHub, Twilio ou tout autre service externe.
Problème : Les services externes ne peuvent pas atteindre localhost:3000. Votre serveur de développement n'est pas accessible depuis Internet.
Scénarios courants où cela perturbe votre flux de travail :
1. Test de Webhook
Des services comme Stripe envoient des confirmations de paiement, GitHub envoie des événements de dépôt, Slack envoie des événements d'interaction — tous sous forme de requêtes POST à votre API. Pendant le développement, ces services ont besoin d'une URL publique pour envoyer des webhooks.

2. URLs de rappel OAuth
Lorsque vous implémentez la fonction "Se connecter avec Google", "Se connecter avec GitHub" ou tout flux OAuth, le fournisseur d'authentification redirige les utilisateurs vers votre application avec un code d'autorisation. L'URL de redirection doit être accessible publiquement et correspondre à celle que vous avez enregistrée auprès du fournisseur.

3. Intégration d'API tierces
Certaines API nécessitent des URLs de rappel pour les opérations asynchrones. Par exemple, les services de transcodage vidéo notifient votre API lorsque le traitement est terminé, ou les processeurs de paiement confirment les transactions.
4. Développement d'applications mobiles
Tester votre API depuis un appareil mobile sur le même réseau échoue souvent car l'application mobile ne peut pas résoudre localhost. Un tunnel vous donne une URL qui fonctionne depuis n'importe quel appareil.
5. Démos clients
Parfois, vous devez montrer le travail en cours à des clients ou des parties prenantes. Le déploiement en environnement de staging pour chaque petite modification ralentit l'itération. Une URL publique temporaire permet aux clients de tester votre environnement de développement.
Comment fonctionne le tunneling de localhost
Les services de tunneling créent une connexion sécurisée entre leurs serveurs cloud et votre machine locale :
Service Externe → Service de Tunneling (URL publique) → Connexion Sécurisée → Votre Localhost:3000
Le processus :
- Vous démarrez un client de tunnel sur votre machine pointant vers votre port local
- Le client se connecte à l'infrastructure cloud du service de tunneling
- Le service attribue une URL publique (par exemple,
https://abc123.ngrok.io) - Les requêtes entrantes vers cette URL publique sont transmises via la connexion chiffrée à votre localhost
- Votre serveur local reçoit la requête comme si elle venait directement du client
- Les réponses sont renvoyées via le tunnel au demandeur
Cela se produit de manière transparente. Votre serveur local n'a pas besoin de savoir qu'il se trouve derrière un tunnel.
Comparaison des services de tunneling populaires
Voici les options les plus populaires en 2026, avec leurs forces et leurs limites :
ngrok (Le plus populaire)
Idéal pour : Les projets établis, les équipes recherchant la fiabilité
ngrok http 3000

Avantages :
- Standard de l'industrie avec une documentation complète
- Interface utilisateur d'inspecteur web pour voir toutes les requêtes
- Domaines personnalisés sur les forfaits payants
- Fonctionnalité de relecture des requêtes
- Terminaison TLS
Inconvénients :
- Le niveau gratuit a une limite de session de 2 heures
- URLs aléatoires sur le niveau gratuit (change à chaque session)
- Le prix commence à 10 $/mois pour les URLs persistantes
Niveau gratuit :
- 1 agent en ligne
- 40 connexions/minute
- URLs aléatoires qui expirent
Plans payants : 8 à 20 $/mois

NPort (Alternative gratuite montante)
Idéal pour : Les développeurs souhaitant éviter les coûts d'abonnement

nport start 3000
Avantages :
- Entièrement gratuit et open-source
- Pas de limites de temps de session
- Sous-domaines personnalisés disponibles
- Option auto-hébergée
- Ensemble de fonctionnalités similaire à celui du niveau gratuit de ngrok
Inconvénients :
- Communauté plus petite (moins de tutoriels)
- Moins mature (lancé en 2025)
- Pas de support commercial
Niveau gratuit :
- Tunnels illimités
- Pas de limites de temps
- Sous-domaines personnalisés

C'est l'outil qui gagne en popularité sur Dev.to, car les développeurs recherchent des alternatives à ngrok sans coûts récurrents.
Cloudflare Tunnel (Idéal pour les environnements proches de la production)
Idéal pour : Les équipes utilisant déjà Cloudflare, les tunnels longue durée

cloudflared tunnel --url http://localhost:3000
Avantages :
- Infrastructure de niveau entreprise
- Protection DDoS incluse
- S'intègre avec Cloudflare Zero Trust
- Pas de limites de bande passante
- Gratuit pour la plupart des cas d'utilisation
Inconvénients :
- Configuration plus complexe
- Nécessite un compte Cloudflare
- Excessif pour de simples tests de webhook
Niveau gratuit :
- Bande passante illimitée
- Tunnels illimités
- Protection DDoS
Localtunnel (Le plus simple)
Idéal pour : Les tests rapides ponctuels, sans installation
npx localtunnel --port 3000
Avantages :
- Pas d'inscription requise
- Zéro configuration
- Sans installation (s'exécute via npx)
- Open-source
Inconvénients :
- Peu fiable (souvent en panne)
- Pas d'inspection des requêtes
- Uniquement des URLs aléatoires
- Documentation minimale

Niveau gratuit :
- Tout est gratuit
- Pas de restrictions de fonctionnalités
Tailscale Funnel (Idéal pour les équipes)
Idéal pour : Le partage privé en équipe, les démos sécurisées

tailscale serve https / http://localhost:3000
tailscale funnel 443 on
Avantages :
- Basé sur WireGuard (rapide, sécurisé)
- Privé par défaut (visible uniquement par votre réseau Tailscale)
- Peut être exposé publiquement si nécessaire
- Excellent pour la collaboration en équipe
Inconvénients :
- Nécessite une configuration Tailscale
- Courbe d'apprentissage plus raide
- Conçu principalement pour les réseaux privés
Niveau gratuit :
- Jusqu'à 100 appareils
- Bande passante illimitée

Tableau comparatif
| Caractéristique | ngrok | NPort | Cloudflare Tunnel | Localtunnel | Tailscale |
|---|---|---|---|---|---|
| Prix | Gratuit/10$+ | Gratuit | Gratuit | Gratuit | Gratuit/Payant |
| Limite de session | 2 heures | Aucune | Aucune | Aucune | Aucune |
| Domaine personnalisé | Payant | Gratuit | Oui | Non | Oui |
| Inspecteur de requêtes | Oui | Basique | Non | Non | Non |
| Complexité de configuration | Faible | Faible | Moyenne | Très faible | Moyenne |
| Fiabilité | Excellente | Bonne | Excellente | Faible | Excellente |
| Idéal pour | Tests de production | Développeurs soucieux des coûts | Entreprise | Tests rapides | Partage d'équipe |
Configurer votre premier tunnel localhost
Passons en revue la configuration avec les outils les plus courants. Nous utiliserons une API Express Node.js comme exemple, mais cela fonctionne avec n'importe quel serveur local.
Exemple : Serveur API local
// server.js
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
console.log('Webhook received:', req.body);
res.json({ received: true });
});
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Option 1 : Utilisation de ngrok
Étape 1 : Installer ngrok
# macOS
brew install ngrok
# Windows (via Chocolatey)
choco install ngrok
# Linux
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
sudo tee /etc/apt/sources.list.d/ngrok.list && \
sudo apt update && sudo apt install ngrok
Étape 2 : Authentification (facultatif mais recommandé)
ngrok config add-authtoken YOUR_AUTH_TOKEN
Étape 3 : Démarrer le tunnel
ngrok http 3000
Sortie :
Session Status online
Account you@example.com (Plan: Free)
Version 3.5.0
Region United States (us)
Forwarding https://abc123.ngrok.io -> http://localhost:3000
Votre API est maintenant accessible à https://abc123.ngrok.io.
Étape 4 : Tester
curl https://abc123.ngrok.io/health
# {"status":"healthy"}
Option 2 : Utilisation de NPort (Alternative gratuite)
Étape 1 : Installer NPort
npm install -g nport-cli
# ou
curl -sSL https://nport.io/install.sh | bash
Étape 2 : Démarrer le tunnel
nport start 3000 --subdomain myapi
Sortie :
✓ Tunnel started successfully
Public URL: https://myapi.nport.io
Local URL: http://localhost:3000
Étape 3 : Tester
curl https://myapi.nport.io/health
# {"status":"healthy"}
Option 3 : Utilisation de Cloudflare Tunnel
Étape 1 : Installer cloudflared
# macOS
brew install cloudflare/cloudflare/cloudflared
# Linux
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
Étape 2 : Tunnel rapide (pas d'inscription requise)
cloudflared tunnel --url http://localhost:3000
Sortie :
2026-01-27T12:00:00Z INF Your quick tunnel is: https://xyz789.trycloudflare.com
Pour les tunnels persistants (nécessite un compte Cloudflare) :
# Connexion
cloudflared tunnel login
# Créer un tunnel
cloudflared tunnel create myapi
# Configurer et exécuter
cloudflared tunnel --config config.yml run myapi
Test des Webhooks avec Apidog
Maintenant que votre localhost est accessible publiquement, testons les webhooks systématiquement à l'aide d'Apidog.
Pourquoi combiner Tunneling + Apidog ?
Le tunneling résout l'accès ; Apidog résout la vérification :
- Le service de tunneling rend votre localhost accessible
- Apidog teste les réponses de votre API, valide les données, automatise les scénarios
Configuration des tests de webhook dans Apidog
Étape 1 : Importer ou créer votre API
- Ouvrez Apidog

2. Créez un nouveau projet

3. Ajoutez votre point de terminaison de webhook :

- Méthode : POST
- URL :
{{base_url}}/webhook - En-têtes :
Content-Type: application/json
Étape 2 : Configurer les variables d'environnement
Configurez deux environnements :
Développement (Tunnelisé) :
{
"base_url": "https://abc123.ngrok.io"
}
Production :
{
"base_url": "https://api.yourapp.com"
}
Cela vous permet de tester le même point de terminaison localement et en production en un seul clic.
Étape 3 : Créer des scénarios de test
Testez ce qui se passe lorsque les webhooks arrivent :
Exemple : Test de webhook de paiement Stripe
// Request Body
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_test123",
"amount": 2000,
"currency": "usd",
"status": "succeeded"
}
}
}
Assertions dans Apidog :
- Le code de statut est égal à 200
- La réponse contient
received: true - Temps de réponse < 1000ms
- Le Content-Type est
application/json
Étape 4 : Simuler les services tiers
Au lieu de déclencher de vrais webhooks depuis Stripe ou GitHub, simulez-les dans Apidog :
- Copiez les exemples de charge utile de webhook à partir de la documentation du service
- Créez des cas de test avec divers scénarios (succès, échec, cas limites)
- Exécutez tous les scénarios contre votre localhost tunnelisé
- Vérifiez que votre API gère correctement chaque cas
Test des rappels OAuth
Scénario : Vous implémentez la fonction "Se connecter avec Google"
Étape 1 : Démarrer le tunnel avec un sous-domaine personnalisé
ngrok http 3000 --subdomain myapp
# URL: https://myapp.ngrok.io
Étape 2 : Configurer la redirection OAuth dans la Google Console
Définir l'URL de rappel : https://myapp.ngrok.io/auth/google/callback
Étape 3 : Tester le flux dans Apidog
- Faites une requête à
/auth/googlepour obtenir l'URL d'autorisation - Suivez la redirection manuellement ou par programme
- Vérifiez que le rappel reçoit le code d'autorisation
- Affirmez que l'échange de jetons fonctionne correctement
Étape 4 : Valider le stockage des jetons
Utilisez Apidog pour :
- Vérifier que les jetons sont stockés en toute sécurité
- Tester le flux de rafraîchissement des jetons
- S'assurer que les jetons expirés sont gérés
Cas d'utilisation courants
1. Tester les webhooks de paiement (Stripe, PayPal)
Défi : Les fournisseurs de paiement envoient des webhooks pour des événements comme les paiements réussis, les remboursements, les litiges.
Solution :
# Démarrer le tunnel
ngrok http 3000
# Configurer l'URL du webhook dans le tableau de bord Stripe
# https://abc123.ngrok.io/webhook/stripe
# Utiliser l'interface de ligne de commande Stripe pour transférer les webhooks de test
stripe listen --forward-to localhost:3000/webhook/stripe
# Déclencher des événements de test
stripe trigger payment_intent.succeeded
Tester avec Apidog :
- Créez des cas de test pour chaque type d'événement
- Vérifiez l'idempotence (gestion des webhooks en double)
- Testez la vérification de signature
- Assurez-vous que les mises à jour de la base de données se produisent correctement
2. Tester les commandes de bot Slack/Discord
Défi : Les plateformes de chat envoient des événements d'interaction lorsque les utilisateurs cliquent sur des boutons ou exécutent des commandes.
Solution :
# Démarrer le tunnel
nport start 3000 --subdomain myslackbot
# Configurer dans l'API Slack :
# Interactivity URL: https://myslackbot.nport.io/slack/interactions
# Slash Commands: https://myslackbot.nport.io/slack/commands
Tester avec Apidog :
- Simulez les clics sur les boutons
- Testez les réponses des commandes slash
- Vérifiez le délai de réponse (Slack exige des réponses <3s)
- Testez les réponses différées avec
response_url
3. Tester les webhooks SMS/Voix (Twilio)
Défi : Twilio envoie des webhooks lorsqu'un SMS arrive ou qu'un appel vocal est reçu.
Solution :
cloudflared tunnel --url http://localhost:3000
Configurez les webhooks TwiML pour qu'ils pointent vers l'URL de votre tunnel.
Tester avec Apidog :
- Simulez les charges utiles SMS entrantes
- Testez différents types de messages (MMS, SMS)
- Vérifiez la validation de signature Twilio
- Testez la génération de TwiML de réponse
4. Test d'API d'applications mobiles
Défi : Tester votre API depuis un appareil physique ou un émulateur.
Problème avec localhost :
// Cela échoue depuis un appareil mobile
fetch('http://localhost:3000/api/users')
Solution avec un tunnel :
// Cela fonctionne de n'importe où
fetch('https://myapi.ngrok.io/api/users')
Tester avec Apidog :
- Générez la documentation de l'API avec l'URL de base tunnelisée
- Partagez avec l'équipe mobile
- Les développeurs mobiles peuvent tester sur votre serveur de développement en direct
- Passez aux URLs de staging/production lorsque vous êtes prêt
5. Tester les webhooks GitHub/GitLab
Défi : Tester les webhooks de dépôt (push, pull request, issues) localement.
Solution :
# Démarrer le tunnel
ngrok http 4000
# Configurer dans les paramètres du dépôt GitHub :
# Webhook URL: https://abc123.ngrok.io/github/webhook
# Content type: application/json
# Events: Push, Pull requests
Tester avec Apidog :
- Simulez les événements de push
- Testez les événements d'ouverture/fermeture de PR
- Vérifiez la validation de signature (X-Hub-Signature)
- Testez la logique de filtrage des branches
Bonnes pratiques de sécurité
Exposer localhost à Internet crée des risques de sécurité. Suivez ces pratiques :
1. Utilisez HTTPS uniquement
Tous les services de tunneling fournissent HTTPS par défaut. N'utilisez jamais HTTP simple pour les tunnels :
# Bon
ngrok http 3000
# Crée https://abc123.ngrok.io
# Mauvais (ne le faites pas)
ngrok http --scheme=http 3000
2. Mettez en œuvre la vérification de signature de webhook
Ne faites pas aveuglément confiance aux webhooks entrants. Vérifiez les signatures :
const crypto = require('crypto');
function verifyStripeSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhook/stripe', (req, res) => {
const signature = req.headers['stripe-signature'];
if (!verifyStripeSignature(req.body, signature, process.env.STRIPE_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Traiter le webhook
});
3. Restreignez l'accès avec l'authentification de base
Ajoutez une authentification à votre tunnel :
# ngrok avec authentification de base
ngrok http 3000 --auth="username:password"
# NPort avec authentification de base
nport start 3000 --auth username:password
Maintenant, les requêtes nécessitent des identifiants :
curl -u username:password https://abc123.ngrok.io/webhook
4. Utilisez des secrets spécifiques à l'environnement
Ne commettez jamais les secrets de webhook ou les clés API :
// .env.development
STRIPE_WEBHOOK_SECRET=whsec_test_abc123
WEBHOOK_TUNNEL_URL=https://abc123.ngrok.io
// .env.production
STRIPE_WEBHOOK_SECRET=whsec_live_xyz789
WEBHOOK_URL=https://api.yourapp.com
5. Surveillez l'accès au tunnel
Utilisez l'inspecteur de requêtes pour surveiller toute activité suspecte :
# ngrok fournit une interface web à :
http://localhost:4040
# Voir toutes les requêtes, réponses, rejouer les attaques
6. Limitez la durée du tunnel
Ne laissez pas les tunnels fonctionner indéfiniment :
# Le tunnel expire automatiquement après 1 heure
ngrok http 3000 --session-duration 1h
7. Validez les sources de requêtes
Vérifiez les adresses IP entrantes ou utilisez des listes blanches :
const allowedIPs = [
'192.0.2.1', // IPs de webhook Stripe
'198.51.100.0/24'
];
app.use('/webhook', (req, res, next) => {
const clientIP = req.ip;
if (!allowedIPs.includes(clientIP)) {
return res.status(403).send('Forbidden');
}
next();
});
Dépannage des problèmes courants
Problème 1 : L'URL du tunnel change à chaque session
Problème : Les tunnels ngrok gratuits utilisent des URLs aléatoires qui changent à chaque redémarrage. Les webhooks configurés avec l'ancienne URL ne fonctionnent plus.
Solutions :
- Utilisez un forfait payant pour des URLs statiques :
ngrok http 3000 --domain=myapp.ngrok.app
- Passez à NPort avec des sous-domaines personnalisés gratuits :
nport start 3000 --subdomain myapp
# Toujours https://myapp.nport.io
- Mettez à jour les webhooks par programme via l'API lorsque le tunnel démarre
Problème 2 : Expiration des webhooks
Problème : Votre serveur local prend trop de temps à répondre. Des services comme Slack exigent des réponses en moins de 3 secondes.
Solution :
Traitez de manière asynchrone :
app.post('/webhook', async (req, res) => {
// Accuser réception immédiatement
res.json({ received: true });
// Traiter en arrière-plan
processWebhookAsync(req.body).catch(console.error);
});
async function processWebhookAsync(data) {
// Effectuer le travail lent ici (base de données, API externes, etc.)
await heavyProcessing(data);
}
Testez les délais d'attente avec Apidog en définissant des limites de délai agressives dans les scénarios de test.
Problème 3 : Erreurs CORS depuis le navigateur
Problème : Le frontend effectuant des requêtes vers l'URL du tunnel obtient des erreurs CORS.
Solution :
Configurez les en-têtes CORS :
const cors = require('cors');
app.use(cors({
origin: [
'http://localhost:3001', // Votre serveur de développement frontend
'https://abc123.ngrok.io' // L'URL de votre tunnel
],
credentials: true
}));
Problème 4 : Limitation de débit sur le niveau gratuit
Problème : Les tunnels gratuits ont des limites de connexion (ngrok : 40/min).
Solutions :
- Regroupez les requêtes de test dans Apidog au lieu de tests individuels en rafale
- Utilisez plusieurs tunnels pour différents services
- Passez au niveau payant si vous testez beaucoup
- Passez à un service illimité comme Cloudflare Tunnel ou NPort
Problème 5 : Le tunnel se déconnecte fréquemment
Problème : L'instabilité du réseau provoque des coupures de tunnel.
Solution :
Utilisez systemd/pm2 pour le redémarrage automatique :
# Créer un service systemd
sudo nano /etc/systemd/system/ngrok.service
[Unit]
Description=ngrok tunnel
After=network.target
[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser
ExecStart=/usr/local/bin/ngrok http 3000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl enable ngrok
sudo systemctl start ngrok
Problème 6 : Impossible d'atteindre le tunnel depuis un réseau spécifique
Problème : Les pare-feu d'entreprise ou les réseaux restrictifs bloquent le trafic du tunnel.
Solutions :
- Utilisez Cloudflare Tunnel (rarement bloqué)
- Changez la région du tunnel pour qu'elle soit plus proche de vous :
ngrok http 3000 --region eu
- Utilisez Tailscale pour un réseau privé au lieu d'un tunnel public
Modèles avancés
Modèle 1 : Tunneling multi-ports
Exposez plusieurs services simultanément :
# Terminal 1 : Serveur API
ngrok http 3000
# Terminal 2 : Serveur de développement frontend
ngrok http 3001
# Terminal 3 : Worker de webhook
ngrok http 3002
Ou utilisez le fichier de configuration ngrok :
# ~/.ngrok2/ngrok.yml
tunnels:
api:
proto: http
addr: 3000
frontend:
proto: http
addr: 3001
worker:
proto: http
addr: 3002
ngrok start --all
Modèle 2 : Tunnel + Docker Compose
# docker-compose.yml
version: '3'
services:
api:
build: .
ports:
- "3000:3000"
ngrok:
image: ngrok/ngrok:latest
command:
- "http"
- "api:3000"
environment:
NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN}
docker-compose up
Modèle 3 : Injection dynamique d'URL de tunnel
Mettez à jour automatiquement votre application avec l'URL du tunnel :
// start-tunnel.js
const ngrok = require('ngrok');
const fs = require('fs');
(async function() {
const url = await ngrok.connect(3000);
console.log(`Tunnel démarré : ${url}`);
// Mettre à jour le fichier .env
fs.appendFileSync('.env', `\nTUNNEL_URL=${url}\n`);
// Mettre à jour le webhook Stripe
await updateStripeWebhook(url);
})();
Modèle 4 : Redirection de requêtes vers plusieurs environnements
Testez le même webhook sur les environnements de développement, de staging et de production :
// webhook-multiplexer.js
app.post('/webhook', async (req, res) => {
const environments = [
'http://localhost:3000',
'https://staging.api.com',
'https://api.yourapp.com'
];
// Transférer vers tous les environnements
const results = await Promise.all(
environments.map(env =>
fetch(`${env}/webhook`, {
method: 'POST',
headers: req.headers,
body: JSON.stringify(req.body)
})
)
);
res.json({ forwarded: results.length });
});
Conclusion
Le test des API localhost qui reçoivent des webhooks ou des rappels ne nécessite pas de déploiement en environnement de staging pour chaque modification. Les services de tunneling créent des URLs publiques temporaires qui permettent aux services externes d'atteindre votre environnement de développement.
Commencez par le niveau gratuit de n'importe quel outil. Si le test de webhook devient une partie quotidienne de votre flux de travail, envisagez des plans payants pour des URLs statiques et des fonctionnalités supplémentaires. Mais pour la plupart des développeurs, les services de tunneling gratuits combinés aux capacités de test d'API d'Apidog offrent tout le nécessaire pour tester efficacement les API localhost.
