npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

Readme

Dynamic Self-Register Proxy

npm version License: ISC

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-proxy

Ou pour une installation globale :

npm install -g dynamic-self-register-proxy

Dé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 start

Le 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-proxy

2. 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 4000

Page 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 manquant
  • 409 - 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 route
  • unregister() - Supprime l'enregistrement
  • listRoutes() - Liste toutes les routes
  • health() - Vérifie l'état du proxy
  • setupGracefulShutdown(server) - Configure l'arrêt propre
  • setupHealthRoute(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:down

Accè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-network

Health 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/health pour ne pas être désenregistrées automatiquement

Licence

ISC