dynamic-self-register-proxy
v1.0.12
Published
Dynamic reverse proxy with self-registration API - applications can register themselves and receive an automatically assigned port
Maintainers
Readme
Dynamic Self-Register Proxy
Un reverse proxy Node.js avec API d'auto-enregistrement, permettant à vos applications de s'enregistrer dynamiquement et de recevoir un port automatiquement attribué.
Cas d'usage
- Conteneur Docker unique exposant un seul port vers l'extérieur
- Microservices dynamiques qui démarrent/s'arrêtent sans configuration manuelle
- Environnement de développement avec plusieurs applications Node.js
Installation
npm install dynamic-self-register-proxyOu pour une installation globale :
npm install -g dynamic-self-register-proxyDémarrage rapide
1. Démarrer le proxy
# Via npx (sans installation globale)
npx dynamic-self-register-proxy
# Ou si installé globalement
dynamic-proxy
# Ou via npm script (développement local)
npm startLe proxy démarre par défaut sur le port 3000. Pour changer le port :
# Windows PowerShell
$env:PROXY_PORT="3002"; npx dynamic-self-register-proxy
# Linux/Mac
PROXY_PORT=3002 npx dynamic-self-register-proxy2. Enregistrer une application
Votre application doit s'enregistrer au démarrage :
const response = await fetch('http://localhost:3000/proxy/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
path: '/myapp', // Chemin d'accès via le proxy
name: 'My App' // Nom de l'application (optionnel)
})
});
const { port } = await response.json();
// port = 4000 (attribué automatiquement)
// Démarrez votre serveur sur ce port
app.listen(port);3. Accéder à votre application
http://localhost:3000/myapp/ → votre application sur le port 4000Page d'accueil
L'URL racine / affiche une page listant tous les serveurs enregistrés avec des liens pour y accéder.
- Navigateurs (
Accept: text/html) → Page HTML avec interface moderne - Clients API (
Accept: application/json) → Réponse JSON
# Accès navigateur : ouvrir http://localhost:3000/
# Accès API
curl -H "Accept: application/json" http://localhost:3000/Réponse JSON :
{
"status": "healthy",
"uptime": 3600,
"count": 2,
"routes": [
{
"path": "/api",
"port": 4000,
"name": "API Server",
"registeredAt": "2026-01-27T10:00:00.000Z",
"target": "http://localhost:4000"
}
],
"availablePorts": 998
}API du Proxy
| Endpoint | Méthode | Description |
|----------|---------|-------------|
| / | GET | Page d'accueil (HTML ou JSON selon Accept header) |
| /proxy/register | POST | Enregistre une nouvelle route |
| /proxy/unregister | DELETE | Supprime une route |
| /proxy/routes | GET | Liste toutes les routes |
| /proxy/health | GET | Health check du proxy |
POST /proxy/register
Enregistre une nouvelle route et attribue un port.
Request:
{
"path": "/myapp",
"name": "My Application",
"port": 4005
}| Champ | Type | Requis | Description |
|-------|------|--------|-------------|
| path | string | ✅ | Chemin URL pour accéder à l'app |
| name | string | ❌ | Nom descriptif |
| port | number | ❌ | Port spécifique (sinon auto-attribué) |
Response (201):
{
"success": true,
"path": "/myapp",
"port": 4000,
"name": "My Application",
"message": "Route registered. Start your server on port 4000"
}Erreurs:
400- Path manquant409- Path ou port déjà utilisé
DELETE /proxy/unregister
Supprime une route enregistrée.
Request:
{
"path": "/myapp"
}Response (200):
{
"success": true,
"path": "/myapp",
"freedPort": 4000
}GET /proxy/routes
Liste toutes les routes enregistrées.
Response:
{
"count": 2,
"routes": [
{
"path": "/api",
"port": 4000,
"name": "API Server",
"registeredAt": "2026-01-27T10:00:00.000Z",
"target": "http://localhost:4000"
},
{
"path": "/web",
"port": 4001,
"name": "Web App",
"registeredAt": "2026-01-27T10:01:00.000Z",
"target": "http://localhost:4001"
}
],
"availablePorts": 998
}GET /proxy/health
Vérifie l'état du proxy.
Response:
{
"status": "healthy",
"uptime": 3600,
"registeredRoutes": 2,
"usedPorts": 2
}Intégration dans votre application
Exemple complet avec Express
const express = require('express');
const PROXY_URL = process.env.PROXY_URL || 'http://localhost:3000';
const APP_PATH = process.env.APP_PATH || '/myapp';
const APP_NAME = process.env.APP_NAME || 'My App';
async function start() {
// 1. S'enregistrer auprès du proxy
const res = await fetch(`${PROXY_URL}/proxy/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: APP_PATH, name: APP_NAME })
});
const { port } = await res.json();
// 2. Créer l'application
const app = express();
app.get('/', (req, res) => {
res.json({ message: 'Hello!' });
});
// 3. Démarrer sur le port attribué
const server = app.listen(port, () => {
console.log(`App accessible via ${PROXY_URL}${APP_PATH}`);
});
// 4. Se désenregistrer à l'arrêt
process.on('SIGTERM', async () => {
await fetch(`${PROXY_URL}/proxy/unregister`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: APP_PATH })
});
server.close();
});
}
start();Utilisation du ProxyClient
Le package inclut un client helper pour faciliter l'enregistrement :
const ProxyClient = require('dynamic-self-register-proxy');
const proxy = new ProxyClient('http://localhost:3000');
const { port } = await proxy.register('/myapp', 'My App');
app.listen(port);
// Arrêt propre automatique
proxy.setupGracefulShutdown(server);Méthodes disponibles :
register(path, name, port?)- Enregistre une routeunregister()- Supprime l'enregistrementlistRoutes()- Liste toutes les routeshealth()- Vérifie l'état du proxysetupGracefulShutdown(server)- Configure l'arrêt propresetupHealthRoute(app, options?)- Ajoute la route de health check
Docker
Build et lancement
# Build
npm run docker:build
# Démarrer (proxy + 2 apps exemples)
npm run docker:up
# Arrêter
npm run docker:downAccès
- Proxy :
http://localhost:8081 - App 1 :
http://localhost:8081/app1 - App 2 :
http://localhost:8081/app2 - Routes :
http://localhost:8081/proxy/routes
Ajouter votre propre service
Dans docker-compose.yml :
services:
my-service:
build: ./my-service
environment:
- PROXY_URL=http://proxy:3000
- APP_PATH=/my-service
- APP_NAME=My Service
depends_on:
- proxy
networks:
- proxy-networkHealth Check Polling
Le proxy vérifie périodiquement que les serveurs enregistrés sont toujours actifs. Si un serveur ne répond pas correctement, il est automatiquement désenregistré.
Implémentation requise
Chaque application enregistrée doit implémenter la route GET /proxy/health qui retourne un code 200 :
// Avec Express
app.get('/proxy/health', (req, res) => {
res.status(200).json({ status: 'healthy' });
});Avec ProxyClient
Le helper ProxyClient fournit une méthode pour ajouter automatiquement cette route :
const ProxyClient = require('dynamic-self-register-proxy');
const proxy = new ProxyClient('http://localhost:3000');
const app = express();
// Ajoute automatiquement GET /proxy/health
proxy.setupHealthRoute(app);
// Ou avec un health check personnalisé
proxy.setupHealthRoute(app, {
healthCheck: async () => {
// Vérifier la connexion à la DB, etc.
const dbOk = await checkDatabase();
return dbOk;
}
});Comportement
- Période de grâce : les nouveaux serveurs ont 60 secondes après l'enregistrement avant d'être vérifiés (laisse le temps au serveur de démarrer)
- Le proxy vérifie tous les serveurs toutes les 30 secondes (par défaut)
- Timeout de 5 secondes par requête de health check
- Si la réponse n'est pas un code 200, le serveur est automatiquement désenregistré
- Les erreurs de connexion (serveur arrêté, timeout) entraînent aussi le désenregistrement
Configuration MCP (Cursor / Claude Desktop)
Pour utiliser ce proxy comme serveur MCP, ajoutez la configuration suivante :
Cursor
Dans votre fichier .cursor/mcp.json :
{
"mcpServers": {
"dynamic-proxy": {
"command": "npx",
"args": ["dynamic-self-register-proxy"],
"env": {
"PROXY_PORT": "3000"
}
}
}
}Claude Desktop
Dans votre fichier de configuration Claude Desktop (claude_desktop_config.json) :
{
"mcpServers": {
"dynamic-proxy": {
"command": "npx",
"args": ["dynamic-self-register-proxy"],
"env": {
"PROXY_PORT": "3000"
}
}
}
}Avec variables d'environnement personnalisées
{
"mcpServers": {
"dynamic-proxy": {
"command": "npx",
"args": ["dynamic-self-register-proxy"],
"env": {
"PROXY_PORT": "8080",
"HEALTH_CHECK_INTERVAL": "60000",
"HEALTH_CHECK_TIMEOUT": "10000",
"HEALTH_CHECK_GRACE_PERIOD": "120000"
}
}
}
}Configuration
| Variable | Défaut | Description |
|----------|--------|-------------|
| PROXY_PORT | 3000 | Port d'écoute du proxy |
| HEALTH_CHECK_INTERVAL | 30000 | Intervalle du health check polling (ms) |
| HEALTH_CHECK_TIMEOUT | 5000 | Timeout pour chaque health check (ms) |
| HEALTH_CHECK_GRACE_PERIOD | 60000 | Période de grâce pour les nouveaux serveurs (ms) |
| PROXY_URL | http://localhost:3000 | URL du proxy (pour les apps) |
| APP_PATH | /example | Chemin de l'application |
| APP_NAME | Example App | Nom de l'application |
Plage de ports
Par défaut, le proxy attribue des ports entre 4000 et 5000 (1000 ports disponibles).
Pour modifier cette plage, éditez proxy.js :
const INTERNAL_PORT_START = 4000;
const INTERNAL_PORT_END = 5000;Fonctionnalités
- Attribution sécurisée des ports : utilisation d'un mutex pour éviter les conflits lors d'enregistrements simultanés
- Période de grâce : les nouveaux serveurs ne sont pas vérifiés immédiatement, leur laissant le temps de démarrer
- Négociation de contenu : l'URL racine
/retourne HTML pour les navigateurs, JSON pour les API - Health check automatique : désenregistrement automatique des serveurs non répondants
📝 Logs et Débogage
Le serveur enregistre ses activités (requêtes, erreurs, enregistrements) dans un fichier de log persistant :
- Windows :
C:\var\log\proxy-server\server.log - Linux/Mac :
/var/log/proxy-server/server.log
Le format des logs inclut la date, l'heure, le PID et le tag [PROXY].
Limitations
- Les routes sont stockées en mémoire (perdues au redémarrage du proxy)
- Pas de persistance des enregistrements
- Pas d'authentification sur l'API de registration
- Les applications doivent implémenter
GET /proxy/healthpour ne pas être désenregistrées automatiquement
Licence
ISC
