A production-style API Gateway built in Node.js. Single entry point that sits in front of your microservices and handles authentication, rate limiting, logging, and request routing — before any request ever reaches a service.
Client
│
▼
[TheRUPOgate :4000]
├── Logger → structured JSON logs + live SSE dashboard
├── Rate Limiter → Redis sliding-window (100 req/min per client)
├── Auth → JWT verify → injects x-user-id + x-user-role
└── Proxy Router → matches path prefix → forwards to service
├── /auth/** → Auth Service :3004 (public)
├── /users/** → User Service :3001 (JWT required)
├── /orders/** → Order Service :3002 (JWT required)
└── /products/** → Product Service :3003 (public)
| Layer | Technology |
|---|---|
| Runtime | Node.js |
| Server | Express |
| Proxying | http-proxy-middleware v3 |
| Auth | jsonwebtoken |
| Rate limiting | ioredis (Redis sorted sets) |
| Security headers | helmet |
| Config | dotenv |
| Dashboard | Server-Sent Events + vanilla HTML/CSS/JS |
TheRUPOgate/
├── src/
│ ├── index.js # Entry point — wires everything together
│ ├── config.js # Route registry + env config
│ ├── dashboard.js # Live monitoring UI (SSE + REST)
│ ├── middleware/
│ │ ├── auth.js # JWT validation + header injection
│ │ ├── rateLimiter.js # Redis sliding-window rate limiter
│ │ └── logger.js # Structured JSON logger + ring buffer
│ ├── proxy/
│ │ └── router.js # Path-prefix proxy routing
│ └── utils/
│ ├── errors.js # Standardized error responses
│ └── events.js # Shared EventEmitter for SSE
├── mock-services/
│ ├── auth-service.js # Issues JWTs → :3004
│ ├── user-service.js # Mock users → :3001
│ ├── order-service.js # Mock orders → :3002
│ └── product-service.js # Mock products → :3003
├── public/
│ └── dashboard.html # Live monitoring dashboard UI
├── .env.example # Environment variable template
└── package.json
git clone https://github.com/BonchitoSky/TheRUPOgate.git
cd TheRUPOgatenpm installcp .env.example .envEdit .env and set your values:
PORT=4000
JWT_SECRET=your-secret-key-here
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
USER_SERVICE_URL=http://localhost:3001
ORDER_SERVICE_URL=http://localhost:3002
PRODUCT_SERVICE_URL=http://localhost:3003
AUTH_SERVICE_URL=http://localhost:3004Open 5 terminal tabs and run one command in each:
# Tab 1 — Gateway
node src/index.js
# Tab 2 — Auth Service
node mock-services/auth-service.js
# Tab 3 — User Service
node mock-services/user-service.js
# Tab 4 — Order Service
node mock-services/order-service.js
# Tab 5 — Product Service
node mock-services/product-service.jsOr use nodemon for auto-restart on file changes:
npx nodemon src/index.jsOpen in your browser after starting the gateway:
http://localhost:4000/dashboard
Shows every request in real time — method, path, status code, latency, and user identity — streamed live via SSE.
curl -X POST http://localhost:4000/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"password"}'curl http://localhost:4000/users/profile \
-H "Authorization: Bearer <your-token>"curl http://localhost:4000/products/curl http://localhost:4000/users/profilecurl http://localhost:4000/healthOn Windows (PowerShell):
# Get token
$res = Invoke-RestMethod -Method Post -Uri "http://localhost:4000/auth/login" `
-ContentType "application/json" `
-Body '{"username":"alice","password":"password"}'
$token = $res.token
# Protected route
Invoke-RestMethod "http://localhost:4000/users/profile" `
-Headers @{ Authorization = "Bearer $token" }
# Public route
Invoke-RestMethod "http://localhost:4000/products/"Every request is timestamped, tagged with a unique x-request-id, and written as structured JSON to stdout. Response timing is measured from arrival to finish. The last 200 entries are kept in memory and streamed to the dashboard via SSE.
Uses a Redis sorted set as a sliding window counter. Each client (by IP or user ID) gets 100 requests per minute. If they exceed the limit they receive a 429 response. If Redis is unavailable the limiter fails open — requests pass through rather than taking the gateway down.
Validates the Authorization: Bearer <token> header on protected routes. On success it strips the raw JWT and injects x-user-id and x-user-role headers for downstream services. Downstream services should only trust these headers from the gateway's internal IP.
Matches the incoming path prefix to a registered route and forwards the request to the correct upstream service. The prefix is stripped before forwarding (/users/profile → /profile on the User Service). Returns a clean 502 if the upstream is unreachable.
Edit src/config.js — add one entry to the routes array:
{
prefix: '/payments',
target: process.env.PAYMENT_SERVICE_URL || 'http://localhost:3005',
requiresAuth: true,
label: 'Payment Service',
},That's it. No other files need to change.
Redis is required for rate limiting. If Redis is not running, the rate limiter fails open (all requests pass through) and you'll see connection errors in the logs. Everything else continues to work normally.
Install Redis locally or run it with Docker:
docker run -p 6379:6379 redisThe mock auth service has two built-in users:
| Username | Password | Role |
|---|---|---|
| alice | password | admin |
| bob | password | user |
MIT