Skip to content
ankittttssPublic

About

Developer-first HTTP egress proxy platform with rate limiting, circuit breaking, request deduplication, cost tracking, and full observability

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Egress Proxy Console (EPC)

A developer-first HTTP egress proxy platform for managing, monitoring, and controlling outbound API calls. Built for teams making expensive external API requests (OpenAI, Twilio, payment processors, etc.), EPC provides rate limiting, circuit breaking, request deduplication, cost tracking, and full observability out of the box.


Table of Contents


Architecture Overview

                    +-------------------+
                    |   React Console   |  :5173
                    |  (Vite + TS)      |
                    +--------+----------+
                             |
                             v
+----------+       +-------------------+       +------------------+
|  SDK /   | ----> |   Egress Proxy    | ----> | External APIs    |
|  CLI     |       |   (Fastify)       |       | (OpenAI, Twilio, |
+----------+       |   :8080           |       |  Stripe, etc.)   |
                   +----+---------+----+       +------------------+
                        |         |
              +---------+         +---------+
              v                             v
    +------------------+          +------------------+
    |   PostgreSQL 15  |          |    Redis 7       |
    |   :5432          |          |    :6379         |
    |                  |          |                  |
    | - Request logs   |          | - Rate limits    |
    | - Domain configs |          | - Circuit state  |
    | - Service keys   |          | - Dedup cache    |
    | - Audit trail    |          | - Key cache      |
    | - Secrets vault  |          |                  |
    +------------------+          +------------------+
              |
    +---------+---------+
    v                   v
+----------+    +-------------+    +-----------+
| pgAdmin  |    | Prometheus  |    |  Grafana  |
| :5050    |    | :9090       |    |  :3000    |
+----------+    +-------------+    +-----------+

Tech Stack

Layer Technology
Backend Node.js 20, Fastify 4, TypeScript, Zod
Database PostgreSQL 15 (Drizzle ORM), 5 migrations
Cache Redis 7 (ioredis)
Frontend React 18, React Router 6, Vite 5, Three.js, CSS
SDK TypeScript, zero dependencies, drop-in fetch() replacement
CLI TypeScript, zero runtime dependencies
Auth JWT (admin), SHA-256 hashed service keys, TOTP 2FA, Argon2
Observability Pino (logging), Prometheus + Grafana (metrics), OpenTelemetry
Infra Docker Compose (Postgres, Redis, pgAdmin, Prometheus, Grafana)
CI GitHub Actions

Repository Structure

Egress/
├── server/                     # Fastify backend
│   ├── src/
│   │   ├── server.ts           # Entry point, graceful shutdown
│   │   ├── app.ts              # App setup, route registration
│   │   ├── config/             # Zod-validated env config
│   │   ├── lib/                # Core utilities
│   │   │   ├── db/             # Drizzle schema + migrations
│   │   │   ├── redis.ts        # Redis singleton
│   │   │   ├── rate-limiter.ts # Token bucket (atomic Lua)
│   │   │   ├── circuit-breaker.ts # 3-state machine
│   │   │   ├── deduplicator.ts # Content-hash cache
│   │   │   ├── forwarder.ts    # HTTP client (undici)
│   │   │   ├── metrics.ts      # Prometheus counters/histograms
│   │   │   ├── logger.ts       # Pino async batched logger
│   │   │   ├── jwt.ts          # JWT signing/verification
│   │   │   ├── crypto.ts       # Key generation, hashing
│   │   │   ├── mailer.ts       # Nodemailer SMTP
│   │   │   └── ...
│   │   ├── plugins/            # auth, observability, RBAC
│   │   └── modules/            # Feature modules
│   │       ├── proxy/          # Main forwarding pipeline
│   │       ├── services/       # Service registry CRUD
│   │       ├── config/         # Domain configuration
│   │       ├── circuit/        # Circuit breaker management
│   │       ├── analytics/      # Cost, latency, request analytics
│   │       ├── auth/           # Login, signup, 2FA, invites
│   │       ├── secrets/        # Encrypted vault
│   │       ├── transforms/     # Request transformations
│   │       ├── webhooks/       # Webhook delivery
│   │       ├── mocks/          # Mock response fixtures
│   │       └── ...
│   ├── test/unit/              # Vitest unit tests
│   ├── Dockerfile              # Multi-stage Node 20 Alpine
│   └── .env.example
│
├── client/                     # React + Vite console
│   ├── src/
│   │   ├── App.tsx             # Route definitions
│   │   ├── api/client.ts       # Typed API wrapper
│   │   ├── components/         # Layout, Toast, CommandPalette, ParticleNetwork
│   │   └── pages/              # 19 route pages
│   └── .env.example
│
├── sdk/                        # @egress-proxy/sdk
│   └── src/index.ts            # EgressClient (zero deps)
│
├── cli/                        # @egress-proxy/cli
│   └── src/index.ts            # egress-proxy command
│
├── ops/                        # Infrastructure config
│   ├── prometheus/             # Scrape config
│   ├── grafana/                # Provisioned dashboards + datasources
│   └── pgadmin/                # Pre-registered server
│
├── docker-compose.yml          # Full infra stack
├── DOCUMENTATION.md            # Complete architecture + API reference
├── PROGRESS.md                 # Project status + verified tests
└── .github/workflows/ci.yml   # CI pipeline

Features

Proxy Pipeline

  • Rate Limiting - Atomic token-bucket algorithm (Lua script) per domain, multi-instance safe
  • Circuit Breaker - 3-state machine (closed / open / half-open), shared via Redis, configurable threshold and reset timeout
  • Retries - Configurable max attempts with exponential, linear, or no backoff + optional jitter
  • Request Deduplication - Content-hash based with configurable TTL (default 100ms)
  • Timeout - Per-domain and per-path configurable timeouts
  • Priority Queueing - High-priority requests skip the queue; low-priority fail fast

Cost Tracking

  • Per-service x domain usage tracking
  • Pricing rules for provider-specific models (OpenAI tokens, Twilio segments, etc.)
  • Monthly budget caps per service
  • Dedup savings analytics

Security

  • JWT authentication for admin users with RBAC (admin, editor, viewer)
  • SHA-256 hashed service keys with Redis caching
  • TOTP 2FA for admin accounts
  • Brute-force login protection (9 attempts / 5 min)
  • Encrypted secrets vault (AES, key decoupled from JWT)
  • Helmet middleware, CORS, graceful shutdown

Console UI (19 pages)

  • Dashboard - 24h overview with request rate, error rate, latency percentiles, circuit states
  • Services - Register services, reveal one-time keys, rotate, delete
  • Domains - Full CRUD for rate limits, circuit breaker, retry, timeout
  • Circuits - Live state per domain, event history, manual reset
  • Forwarder - Interactive request builder with full response inspection
  • Analytics - Tabbed views: requests, latency, failures, dedup, cost
  • Secrets - Encrypted vault management
  • Transforms - Header injection, URL rewrite with secret interpolation
  • Mocks - Mock response fixtures for dev/test
  • Webhooks - Rule-based alerting
  • Audit Log - Configuration change history
  • Admin Management - User CRUD, role assignment, invite flow
  • Account - Profile settings, TOTP 2FA setup
  • Command Palette - Keyboard-accessible navigation (Ctrl+K)
  • 3D Particle Network - Three.js visualization on login

Developer Experience

  • SDK - Zero-dependency TypeScript SDK, drop-in fetch() replacement
  • CLI - Command-line management tool for services, domains, secrets
  • Request Replay - Re-forward historical requests from the UI
  • Live Tail - WebSocket streaming of real-time request logs

Getting Started

Prerequisites

1. Clone the repository

git clone https://github.com/YourUsername/Egress.git
cd Egress

2. Start infrastructure

docker compose up -d

This starts PostgreSQL, Redis, pgAdmin, Prometheus, and Grafana.

3. Set up the backend

cd server
npm install
cp .env.example .env          # Edit if needed (defaults work for local dev)
npx drizzle-kit generate      # Only if schema changed
npm run db:migrate

4. Set up the frontend

cd ../client
npm install
cp .env.example .env

5. Run in development

# Terminal 1 - Backend (http://localhost:8080)
cd server && npm run serve

# Terminal 2 - Frontend (http://localhost:5173)
cd client && npm run dev

6. First-time bootstrap

  1. Open http://localhost:5173
  2. Click Sign Up to create the first admin account and tenant
  3. Create your first service from the Services page
  4. Save the one-time service key (it won't be shown again)
  5. Configure domain rules from the Domains page

Service URLs

Service URL Credentials
Egress Proxy http://localhost:8080 X-Service-Key header
Console UI http://localhost:5173 Admin login
pgAdmin http://localhost:5050 admin@example.com / admin
Prometheus http://localhost:9090 --
Grafana http://localhost:3000 admin / admin
PostgreSQL localhost:5432 egress / egress
Redis localhost:6379 --

Environment Variables

Server (server/.env)

Variable Required Default Description
NODE_ENV No development development, production, or test
PORT No 8080 Server port
HOST No 0.0.0.0 Server host
LOG_LEVEL No info Pino log level
DATABASE_URL Yes -- PostgreSQL connection string
REDIS_URL No redis://localhost:6379 Redis connection string
JWT_SECRET Prod Auto-generated in dev Min 32 chars; required in production
JWT_EXPIRES_IN No 24h JWT token expiration
SECRETS_ENCRYPTION_KEY Prod Falls back to JWT_SECRET Vault encryption key (min 32 chars)
CORS_ORIGINS No http://localhost:5173 Comma-separated allowed origins
DEFAULT_REQUEST_TIMEOUT_MS No 10000 Default proxy request timeout
DEDUP_TTL_MS No 100 Deduplication cache TTL
LOG_BATCH_SIZE No 100 Async log batch size
LOG_FLUSH_INTERVAL_MS No 250 Log flush interval
REQUEST_LOG_RETENTION_DAYS No 30 Request log retention period
SERVICE_KEY_CACHE_TTL_S No 300 Redis service key cache TTL
SMTP_URL No -- SMTP connection (logs to stdout if unset)
EMAIL_FROM No noreply@egress.local Sender address for emails
APP_URL No http://localhost:5173 Frontend URL (used in emails)

Client (client/.env)

Variable Required Default Description
VITE_API_URL Yes -- Backend API base URL

API Reference

Health

GET /health/live              # Liveness probe
GET /health/ready             # Readiness probe (checks DB + Redis)

Proxy

POST /proxy/forward           # Forward a request through the pipeline

Request body:

{
  "url": "https://api.openai.com/v1/chat/completions",
  "method": "POST",
  "headers": { "Authorization": "Bearer sk-..." },
  "body": { "model": "gpt-4o-mini", "messages": [...] },
  "timeout": 15000,
  "priority": "high"
}

Response:

{
  "status": 200,
  "headers": { "content-type": "application/json" },
  "body": { "choices": [...] },
  "meta": {
    "request_id": "uuid",
    "latency_ms": 234,
    "attempts": 1,
    "cached": false,
    "circuit": "closed",
    "cost_cents": 12
  }
}

Services

POST   /services                  # Create service (first call is bootstrap)
GET    /services                  # List services
DELETE /services/:id              # Delete service
POST   /services/:id/rotate-key  # Rotate service key

Domain Configuration

GET    /config/domains            # List domain configs
GET    /config/domains/:domain    # Get domain config
POST   /config/domains            # Create domain config
PATCH  /config/domains/:domain    # Update domain config
DELETE /config/domains/:domain    # Delete domain config

Circuit Breakers

GET    /circuit-breakers              # List all circuit states
GET    /circuit-breakers/:domain      # Get circuit state for domain
POST   /circuit-breakers/:domain/reset # Manually reset circuit

Analytics

GET /analytics/requests         # Request volume over time
GET /analytics/latency          # Latency percentiles
GET /analytics/failures         # Failure breakdown
GET /analytics/circuit-events   # Circuit state transitions
GET /analytics/cost             # Cost per service x domain
GET /analytics/dedup            # Dedup hit rate

Auth

POST /auth/signup               # Create first admin + tenant
POST /auth/login                # Admin login (returns JWT)
POST /auth/forgot-password      # Password reset request
POST /auth/reset-password       # Reset with token
POST /auth/invite               # Invite user to tenant

Secrets Vault

GET    /secrets                 # List secrets (names only)
POST   /secrets                 # Create encrypted secret
PATCH  /secrets/:id             # Update secret
DELETE /secrets/:id             # Delete secret

Transforms, Mocks, Webhooks

GET/POST/PATCH/DELETE /transforms     # Request transformation rules
GET/POST/PATCH/DELETE /mocks          # Mock response fixtures
GET/POST/PATCH/DELETE /webhooks       # Webhook delivery targets

Full API documentation with schemas is in DOCUMENTATION.md.


SDK Usage

Install the SDK in your application:

npm install @egress-proxy/sdk

Drop-in fetch replacement

import { EgressClient } from '@egress-proxy/sdk';

const egress = new EgressClient({
  proxyUrl: 'http://localhost:8080',
  serviceKey: process.env.EGRESS_PROXY_KEY!,
});

// Use like native fetch() - all requests go through the proxy
const res = await egress.fetch('https://api.openai.com/v1/chat/completions', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.OPENAI_KEY}` },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'hello' }],
  }),
});

const data = await res.json();

// Proxy metadata available in response headers
console.log(res.headers.get('x-egress-latency-ms'));   // "234"
console.log(res.headers.get('x-egress-attempts'));      // "1"
console.log(res.headers.get('x-egress-cost-cents'));    // "12"

Low-level forward (structured metadata)

const r = await egress.forward('https://api.openai.com/v1/chat/completions', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.OPENAI_KEY}` },
  body: JSON.stringify({ model: 'gpt-4o-mini', messages: [...] }),
});

console.log(r.meta.latency_ms);    // 234
console.log(r.meta.attempts);      // 1
console.log(r.meta.circuit);       // "closed"
console.log(r.meta.cost_cents);    // 12

CLI Usage

# Login
egress-proxy login admin@example.com

# Services
egress-proxy services list
egress-proxy services create --name order-service --budget 10000
egress-proxy services rotate <service-id>

# Domains
egress-proxy domains list
egress-proxy domains create --domain api.openai.com --rate 60 --window 1m

# Secrets
egress-proxy secrets set --name openai_prod --value "sk-..."

# Status
egress-proxy status

Observability

Prometheus Metrics (exposed at /metrics)

Metric Type Description
egress_forwarded_requests_total Counter Requests by domain, service, status
egress_request_latency_ms Histogram Latency distribution (p50/p95/p99)
egress_circuit_breaker_state Gauge 0=closed, 1=open, 2=half-open
egress_dedup_cache_hits Counter Deduplicated request count
egress_rate_limit_queue_depth Gauge Rate limiter queue depth

Grafana Dashboards (auto-provisioned)

Two dashboards are provisioned automatically at boot:

  1. Egress Proxy - Request rate by domain/status, latency percentiles, circuit breaker state, error rate, dedup savings, process memory
  2. Egress Proxy Per-Service - Service-level breakdowns

Logging

Structured JSON logging via Pino with async batched writes (100 logs/batch, 250ms flush). Never blocks the request path.


Authentication & Authorization

Admin Users (JWT)

  • JWT tokens issued at login, stored in HTTP-only cookies
  • 24h expiration (configurable)
  • RBAC roles: admin, editor, viewer
  • Optional TOTP 2FA
  • Brute-force protection: 9 attempts per 5-minute window

Service Keys (API)

  • SHA-256 hashed (plaintext never stored)
  • Passed via X-Service-Key header
  • Cached in Redis (300s TTL)
  • Per-service: rate limits, IP allowlist, domain scopes, expiration, monthly budget

Database Schema

Multi-tenant PostgreSQL schema with the following primary tables:

Table Purpose
tenants Multi-tenancy root, workspace isolation
users Admin users per tenant, password + TOTP 2FA
services Service registry, hashed API keys, budgets
secrets Encrypted vault for upstream credentials
domain_configs Rate limits, circuit breaker, retry, timeout settings
path_configs Path-scoped overrides on domain configs
transforms Request transformations (header inject, URL rewrite)
mocks Mock response fixtures
webhooks Webhook delivery targets + trigger rules
pricing Cost rules per provider/model
request_logs Full request/response audit trail (30-day retention)
circuit_events Circuit breaker state transitions
audit_log Admin action audit trail

CI/CD

GitHub Actions runs on push/PR to main:

Job Steps
server Build, typecheck, test (with Postgres + Redis)
client Build, typecheck
sdk Build
cli Build

Running Tests

cd server
npm test              # Runs 11 unit tests via Vitest

Tests cover:

  • Configuration schema validation
  • Deduplicator content hashing
  • Rate limiter token bucket logic
  • Circuit breaker state transitions

Verified End-to-End Tests

# Test Result
1 Health live + ready Redis + DB reachable
2 Bootstrap service registration Key returned
3 Auth rejects missing key HTTP 401
4 Domain config upsert Persisted, cached
5 Proxy forward to httpbin HTTP 200, attempts=1, circuit=closed
6 Retry on 503 3 attempts, surfaced as BadGateway
7 Deduplication 9ms cached vs 1580ms first request
8 Circuit breaker opens 4th call blocked with CircuitOpen
9 Manual circuit reset State returned to closed
10 Analytics endpoints All 6 returning aggregates
11 Prometheus scrape Counters visible
12 Grafana dashboard Datasource + dashboard provisioned
13 Unit tests 11/11 passing

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is provided as-is for educational and development purposes.

About

Developer-first HTTP egress proxy platform with rate limiting, circuit breaking, request deduplication, cost tracking, and full observability

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages