dynamic-self-register-proxy 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +45 -1
  2. package/package.json +1 -1
  3. package/proxy.js +49 -3
package/README.md CHANGED
@@ -75,10 +75,44 @@ app.listen(port);
75
75
  http://localhost:3000/myapp/ → votre application sur le port 4000
76
76
  ```
77
77
 
78
+ ## Page d'accueil
79
+
80
+ L'URL racine `/` affiche une page listant tous les serveurs enregistrés avec des liens pour y accéder.
81
+
82
+ - **Navigateurs** (`Accept: text/html`) → Page HTML avec interface moderne
83
+ - **Clients API** (`Accept: application/json`) → Réponse JSON
84
+
85
+ ```bash
86
+ # Accès navigateur : ouvrir http://localhost:3000/
87
+
88
+ # Accès API
89
+ curl -H "Accept: application/json" http://localhost:3000/
90
+ ```
91
+
92
+ **Réponse JSON :**
93
+ ```json
94
+ {
95
+ "status": "healthy",
96
+ "uptime": 3600,
97
+ "count": 2,
98
+ "routes": [
99
+ {
100
+ "path": "/api",
101
+ "port": 4000,
102
+ "name": "API Server",
103
+ "registeredAt": "2026-01-27T10:00:00.000Z",
104
+ "target": "http://localhost:4000"
105
+ }
106
+ ],
107
+ "availablePorts": 998
108
+ }
109
+ ```
110
+
78
111
  ## API du Proxy
79
112
 
80
113
  | Endpoint | Méthode | Description |
81
114
  |----------|---------|-------------|
115
+ | `/` | GET | Page d'accueil (HTML ou JSON selon Accept header) |
82
116
  | `/proxy/register` | POST | Enregistre une nouvelle route |
83
117
  | `/proxy/unregister` | DELETE | Supprime une route |
84
118
  | `/proxy/routes` | GET | Liste toutes les routes |
@@ -332,6 +366,7 @@ proxy.setupHealthRoute(app, {
332
366
 
333
367
  ### Comportement
334
368
 
369
+ - **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)
335
370
  - Le proxy vérifie tous les serveurs toutes les **30 secondes** (par défaut)
336
371
  - Timeout de **5 secondes** par requête de health check
337
372
  - Si la réponse n'est pas un code **200**, le serveur est automatiquement désenregistré
@@ -388,7 +423,8 @@ Dans votre fichier de configuration Claude Desktop (`claude_desktop_config.json`
388
423
  "env": {
389
424
  "PROXY_PORT": "8080",
390
425
  "HEALTH_CHECK_INTERVAL": "60000",
391
- "HEALTH_CHECK_TIMEOUT": "10000"
426
+ "HEALTH_CHECK_TIMEOUT": "10000",
427
+ "HEALTH_CHECK_GRACE_PERIOD": "120000"
392
428
  }
393
429
  }
394
430
  }
@@ -402,6 +438,7 @@ Dans votre fichier de configuration Claude Desktop (`claude_desktop_config.json`
402
438
  | `PROXY_PORT` | `3000` | Port d'écoute du proxy |
403
439
  | `HEALTH_CHECK_INTERVAL` | `30000` | Intervalle du health check polling (ms) |
404
440
  | `HEALTH_CHECK_TIMEOUT` | `5000` | Timeout pour chaque health check (ms) |
441
+ | `HEALTH_CHECK_GRACE_PERIOD` | `60000` | Période de grâce pour les nouveaux serveurs (ms) |
405
442
  | `PROXY_URL` | `http://localhost:3000` | URL du proxy (pour les apps) |
406
443
  | `APP_PATH` | `/example` | Chemin de l'application |
407
444
  | `APP_NAME` | `Example App` | Nom de l'application |
@@ -417,6 +454,13 @@ const INTERNAL_PORT_START = 4000;
417
454
  const INTERNAL_PORT_END = 5000;
418
455
  ```
419
456
 
457
+ ## Fonctionnalités
458
+
459
+ - **Attribution sécurisée des ports** : utilisation d'un mutex pour éviter les conflits lors d'enregistrements simultanés
460
+ - **Période de grâce** : les nouveaux serveurs ne sont pas vérifiés immédiatement, leur laissant le temps de démarrer
461
+ - **Négociation de contenu** : l'URL racine `/` retourne HTML pour les navigateurs, JSON pour les API
462
+ - **Health check automatique** : désenregistrement automatique des serveurs non répondants
463
+
420
464
  ## Limitations
421
465
 
422
466
  - Les routes sont stockées en mémoire (perdues au redémarrage du proxy)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynamic-self-register-proxy",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Dynamic reverse proxy with self-registration API - applications can register themselves and receive an automatically assigned port",
5
5
  "main": "proxy-client.js",
6
6
  "bin": {
package/proxy.js CHANGED
@@ -14,6 +14,7 @@ const INTERNAL_PORT_START = 4000;
14
14
  const INTERNAL_PORT_END = 5000;
15
15
  const HEALTH_CHECK_INTERVAL = process.env.HEALTH_CHECK_INTERVAL || 30000; // 30 secondes par défaut
16
16
  const HEALTH_CHECK_TIMEOUT = process.env.HEALTH_CHECK_TIMEOUT || 5000; // 5 secondes timeout
17
+ const HEALTH_CHECK_GRACE_PERIOD = process.env.HEALTH_CHECK_GRACE_PERIOD || 60000; // 60 secondes de grâce pour les nouveaux serveurs
17
18
 
18
19
  // ============================================
19
20
  // REGISTRY - Stockage des routes en mémoire
@@ -166,19 +167,36 @@ async function unregisterServer(path) {
166
167
  }
167
168
  }
168
169
 
170
+ /**
171
+ * Vérifie si un serveur est encore dans sa période de grâce
172
+ * @param {object} route - Les informations de la route
173
+ * @returns {boolean} - true si le serveur est encore en période de grâce
174
+ */
175
+ function isInGracePeriod(route) {
176
+ const registeredAt = new Date(route.registeredAt).getTime();
177
+ const now = Date.now();
178
+ return (now - registeredAt) < HEALTH_CHECK_GRACE_PERIOD;
179
+ }
180
+
169
181
  /**
170
182
  * Effectue un health check sur tous les serveurs enregistrés
183
+ * Les serveurs récemment enregistrés (dans la période de grâce) sont ignorés
171
184
  */
172
185
  async function performHealthChecks() {
173
186
  if (registry.routes.size === 0) {
174
187
  return;
175
188
  }
176
189
 
177
- console.log(`[HEALTH CHECK] Checking ${registry.routes.size} registered server(s)...`);
178
-
179
190
  const checks = [];
191
+ let skippedCount = 0;
180
192
 
181
193
  for (const [path, route] of registry.routes.entries()) {
194
+ // Ignore les serveurs en période de grâce
195
+ if (isInGracePeriod(route)) {
196
+ skippedCount++;
197
+ continue;
198
+ }
199
+
182
200
  checks.push(
183
201
  checkServerHealth(path, route).then(isHealthy => ({
184
202
  path,
@@ -188,6 +206,16 @@ async function performHealthChecks() {
188
206
  );
189
207
  }
190
208
 
209
+ // Si tous les serveurs sont en période de grâce, pas de log
210
+ if (checks.length === 0) {
211
+ if (skippedCount > 0) {
212
+ console.log(`[HEALTH CHECK] ${skippedCount} server(s) in grace period, skipping checks`);
213
+ }
214
+ return;
215
+ }
216
+
217
+ console.log(`[HEALTH CHECK] Checking ${checks.length} server(s)...${skippedCount > 0 ? ` (${skippedCount} in grace period)` : ''}`);
218
+
191
219
  const results = await Promise.all(checks);
192
220
 
193
221
  for (const { path, isHealthy } of results) {
@@ -401,6 +429,7 @@ app.get('/proxy/health', (req, res) => {
401
429
  /**
402
430
  * GET /
403
431
  * Page d'accueil listant tous les serveurs disponibles
432
+ * Retourne du JSON si le client l'accepte (API), sinon du HTML (navigateur)
404
433
  */
405
434
  app.get('/', (req, res) => {
406
435
  const routes = [];
@@ -409,13 +438,29 @@ app.get('/', (req, res) => {
409
438
  path,
410
439
  port: value.port,
411
440
  name: value.name,
412
- registeredAt: value.registeredAt
441
+ registeredAt: value.registeredAt,
442
+ target: `http://localhost:${value.port}`
413
443
  });
414
444
  });
415
445
 
416
446
  // Tri par nom
417
447
  routes.sort((a, b) => a.name.localeCompare(b.name));
418
448
 
449
+ // Si le client accepte JSON (et pas spécifiquement HTML), retourne du JSON
450
+ const acceptHeader = req.get('Accept') || '';
451
+ const wantsJson = acceptHeader.includes('application/json') ||
452
+ (acceptHeader.includes('*/*') && !acceptHeader.includes('text/html'));
453
+
454
+ if (wantsJson) {
455
+ return res.json({
456
+ status: 'healthy',
457
+ uptime: process.uptime(),
458
+ count: routes.length,
459
+ routes,
460
+ availablePorts: (INTERNAL_PORT_END - INTERNAL_PORT_START) - registry.usedPorts.size
461
+ });
462
+ }
463
+
419
464
  const html = `
420
465
  <!DOCTYPE html>
421
466
  <html lang="fr">
@@ -728,6 +773,7 @@ app.listen(PROXY_PORT, () => {
728
773
  console.log(`Listening on port ${PROXY_PORT}`);
729
774
  console.log(`Internal ports range: ${INTERNAL_PORT_START}-${INTERNAL_PORT_END}`);
730
775
  console.log(`Health check interval: ${HEALTH_CHECK_INTERVAL}ms`);
776
+ console.log(`Health check grace period: ${HEALTH_CHECK_GRACE_PERIOD}ms`);
731
777
  console.log('');
732
778
  console.log('API Endpoints:');
733
779
  console.log(' POST /proxy/register - Register a new route');