Skip to content

ayushkumar912/RedisLink

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RedisLink - Enterprise-Grade URL Shortening Service

Status Version Node.js MongoDB Redis

Architecture

+------------------------------------------------------------------------------------------------------------------+
|                                         RedisLink - URL Shortener                                                |
+------------------------------------------------------------------------------------------------------------------+

                                          +------------------+
                                          |     [Client]     |
                                          +--------+---------+
                                                   |
                                                   v
+--------------------------------------------------+-------------------------------------------------+
|                                    [Express Middleware Layer]                                       |
|   [CORS] --> [Helmet] --> [Morgan Logger] --> [Input Sanitizer] --> [Rate Limiter (Redis-backed)]   |
+--------------------------------------------------+-------------------------------------------------+
                                                   |
                        +-------------------------++--------------------------+
                        |                          |                          |
                        v                          v                          v
             +----------+----------+   +----------+---------+   +------------+--------+
             |  POST /api/v1/url/  |   | GET /:urlCode      |   | GET /api/v1/url/    |
             |  shorten | /bulk    |   | (Redirect)         |   | :urlCode/stats      |
             +----------+----------+   +----------+---------+   +------------+--------+
                        |                          |                          |
                        v                          v                          v
             +----------+----------+   +----------+---------+   +------------+--------+
             | [Validator Layer]   |   | [Validator Layer]  |   | [Validator Layer]   |
             | Schema + Sanitize   |   | Code format check  |   | Code format check   |
             | + Axios URL check   |   +----------+---------+   +------------+--------+
             +----+----+-----------+              |                          |
                  |    |                          v                          v
                  |  [Axios] --> [External URL]  ++---------------------------+
                  |              Reachability    |    [Controller Layer]      |
                  v              Check           |  (Thin HTTP Handlers)      |
          +-------+---------+                   ++-----------+--------------++
          | [Controller]    |                    |           |               |
          | createUrl       |                    v           v               v
          | bulkCreate      |            +-------+----+ +----+------+ +------+------+
          +-------+---------+            | getLongUrl | | getStats  | |             |
                  |                      +-------+----+ +----+------+ |             |
                  v                              |           |         |             |
          +-------+-------------------------+    |           |         |             |
          |         [Service Layer]         |<---+-----------+---------+             |
          |  createShortUrl / bulkCreate    |                                        |
          |  getLongUrl / getUrlStats       |                                        |
          +--+--+--+-----+----------------++                                        |
             |  |  |     |                                                           |
             |  |  |     +-------> [MongoDB Model] -----> [MongoDB]                 |
             |  |  |                  findOne / create      redislinks collection    |
             |  |  |                  updateOne ($inc)       urlCode, shortUrl,      |
             |  |  |                                         longUrl, clicks,        |
             |  |  |                                         expiresAt               |
             |  |  |                                                                 |
             |  |  +-----------> [Redis Client] -----> [Redis Cache]                |
             |  |                  GET urlCode            L1: urlCode -> longUrl     |
             |  |                  SET urlCode            L1: longUrl -> urlCode     |
             |  |                  DEL (expired)          Rate limit keys            |
             |  |                                         TTL: 24hr                 |
             |  |                                                                    |
             |  +---------------> [Fire-and-Forget]                                 |
             |                    incrementClicks()                                  |
             |                    (async, no await)                                  |
             |                                                                       |
             +-----> [Error Handler] --> [AppError / ValidationError / NotFoundError / DatabaseError]
                     Centralized
                     Middleware

Enterprise Architecture

Runtime Environment: Node.js with Express.js v4.18.2 Database Layer: MongoDB with Mongoose ODM v7.2.2 + Connection Pooling Caching Layer: Redis v4 (native Promise API) with Connection Management & Retry Logic Service Layer: Dedicated business logic layer decoupled from controllers Validation: Multi-layer validation with sanitization Security: Helmet.js + CORS + Input sanitization + Redis-based Rate Limiting Error Handling: Custom error classes with proper HTTP status codes Monitoring: Health checks + Request logging + Graceful shutdown

Production-Ready Features

  • Service Layer Architecture: Business logic fully decoupled from controllers
  • Redis-Based Rate Limiting: Per-IP throttling (100 req/15min global, 20 req/15min for shorten)
  • Analytics: Click tracking per short URL with stats endpoint
  • Custom Short Codes: User-defined vanity codes (3–20 chars, alphanumeric + -_)
  • Bulk URL Shortening: Batch processing of up to 10 URLs in a single request
  • API Versioning: All mutation/query endpoints versioned under /api/v1
  • URL Expiration: Optional TTL per short URL via expiresAt field
  • Robust Error Handling: Custom error classes and centralized error middleware
  • Input Validation & Sanitization: XSS prevention and comprehensive URL validation
  • Connection Resilience: Auto-retry logic for Redis and MongoDB connections
  • Health Monitoring: Real-time service status and connection monitoring
  • Graceful Shutdown: Clean resource cleanup on server termination
  • Security Headers: Production-grade security middleware
  • Request Logging: Detailed HTTP request logging with Morgan
  • Cache Optimization: Intelligent caching with TTL management
  • Fail-Fast Config: Server exits immediately on missing required environment variables

Project Structure

src/
├── app.js                    # Express app with middleware chain
├── index.js                  # Server with graceful startup/shutdown
├── config/
│   ├── index.js             #   Centralized configuration + env validation
│   └── database.js          #   Database connection manager
├── controllers/              # Thin controllers — delegate to service layer
│   └── urlController.js     #   createUrl, getUrl, getStats, bulkCreate
├── middleware/               # Custom middleware
│   ├── errorHandler.js      #   Error handling & custom error classes
│   └── rateLimiter.js       #   Redis-based per-IP rate limiting
├── models/                   # Database models
│   └── urlModel.js          #   MongoDB schema (clicks, expiresAt added)
├── routes/                   # API route definitions
│   ├── route.js             #   Root routes + mounts /api/v1
│   └── v1.js                #   Versioned API routes
├── services/                 # Business logic layer
│   └── urlService.js        #   createShortUrl, getLongUrl, stats, bulk
├── validators/               # Input validation & sanitization
│   └── urlValidator.js      #   URL + customCode + expiresAt + bulk validation
└── utils/                    # Utility modules
    ├── axiosValidation.js   #   External URL reachability check
    └── redisClient.js       #   Redis v4 manager (incr, expire, set, get, del)

Database Schema

MongoDB Collection: redislinks

  • urlCode: String (required, unique, lowercase, trimmed) — Short identifier
  • longUrl: String (required, regex validated) — Original URL
  • shortUrl: String (required, unique, trimmed) — Complete shortened URL
  • clicks: Number (default: 0) — Redirect count
  • expiresAt: Date (default: null) — Optional expiry timestamp
  • createdAt / updatedAt: Auto-generated timestamps
{
  urlCode:   { type: String, required: true, unique: true, lowercase: true, trim: true },
  longUrl:   { type: String, required: true, validate: { validator: urlRegex } },
  shortUrl:  { type: String, required: true, unique: true, trim: true },
  clicks:    { type: Number, default: 0 },
  expiresAt: { type: Date,   default: null }
}

API Endpoints

Welcome & Status

GET /

Returns service info and all available endpoints.


URL Shortening

POST /api/v1/url/shorten
Content-Type: application/json

Minimal request:

{ "longUrl": "https://www.google.com" }

Full request (all optional fields):

{
  "longUrl": "https://www.google.com",
  "customCode": "my-google",
  "expiresAt": "2027-01-01T00:00:00.000Z"
}

Response (201 Created for new, 200 OK for existing):

{
  "status": true,
  "message": "Short URL created successfully",
  "data": {
    "urlCode": "my-google",
    "shortUrl": "http://localhost:3000/my-google",
    "longUrl": "https://www.google.com",
    "expiresAt": "2027-01-01T00:00:00.000Z"
  }
}

Bulk URL Shortening

POST /api/v1/url/bulk
Content-Type: application/json
{
  "urls": [
    { "longUrl": "https://www.google.com" },
    { "longUrl": "https://github.com", "customCode": "gh" },
    { "longUrl": "https://invalid-url-xyz.com" }
  ]
}

Response (207 Multi-Status):

{
  "status": true,
  "message": "Processed 3 URL(s)",
  "data": [
    { "success": true,  "longUrl": "https://www.google.com", "data": { "urlCode": "aB3dE4fG9", "shortUrl": "..." } },
    { "success": true,  "longUrl": "https://github.com",     "data": { "urlCode": "gh",        "shortUrl": "..." } },
    { "success": false, "longUrl": "https://invalid-url-xyz.com", "error": "URL is not accessible or invalid" }
  ]
}

URL Redirection

GET /:urlCode
HTTP/1.1 302 Found
Location: https://www.google.com

Returns 404 if the code doesn't exist, or if the URL has expired.


URL Stats

GET /api/v1/url/:urlCode/stats
{
  "status": true,
  "data": {
    "urlCode": "my-google",
    "shortUrl": "http://localhost:3000/my-google",
    "longUrl": "https://www.google.com",
    "clicks": 42,
    "createdAt": "2026-03-31T10:00:00.000Z",
    "expiresAt": "2027-01-01T00:00:00.000Z"
  }
}

Health Check

GET /health
{
  "status": "ok",
  "timestamp": "2026-03-31T10:00:00.000Z",
  "uptime": 32.87,
  "environment": "development",
  "services": {
    "database": { "status": "connected", "readyState": 1 },
    "redis": { "status": "connected", "retryCount": 0 }
  }
}

Rate Limiting

All endpoints are protected by Redis-based per-IP rate limiting. Responses include rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
Endpoint Limit
All routes 100 requests / 15 min
POST /api/v1/url/shorten 20 requests / 15 min
POST /api/v1/url/bulk 20 requests / 15 min

Rate limiting degrades gracefully — if Redis is unavailable, requests pass through without throttling.


Performance & Caching Strategy

Multi-Layer Caching

  • L1 Cache: Redis v4 with 24-hour TTL (native Promise API, no promisify wrappers)
  • L2 Cache: MongoDB with indexed queries
  • Cache-First Strategy: Redis → MongoDB → 404

Optimizations

  • Connection Pooling: MongoDB connection reuse
  • Index Optimization: Unique indexes on urlCode and shortUrl
  • Async Processing: Non-blocking I/O throughout
  • Fire-and-Forget Clicks: Click increments are non-blocking (don't delay redirects)

Quick Start Guide

Prerequisites

  • Node.js v16+
  • MongoDB (running on port 27017)
  • Redis (running on port 6379)

Installation

# Clone and install
git clone <repository-url>
cd RedisLink
npm install

# Environment setup
cp .env.example .env
# Configure MongoDB and Redis connection strings

# Start services (macOS with Homebrew)
brew services start mongodb/brew/mongodb-community
brew services start redis

# Start RedisLink
npm start

Test the API

# Health check
curl http://localhost:3000/health

# Create short URL
curl -X POST http://localhost:3000/api/v1/url/shorten \
  -H "Content-Type: application/json" \
  -d '{"longUrl": "https://www.google.com"}'

# Create with custom code + expiry
curl -X POST http://localhost:3000/api/v1/url/shorten \
  -H "Content-Type: application/json" \
  -d '{"longUrl": "https://www.google.com", "customCode": "goog", "expiresAt": "2027-12-31T00:00:00.000Z"}'

# Bulk shorten
curl -X POST http://localhost:3000/api/v1/url/bulk \
  -H "Content-Type: application/json" \
  -d '{"urls": [{"longUrl": "https://www.google.com"}, {"longUrl": "https://github.com"}]}'

# Get stats
curl http://localhost:3000/api/v1/url/goog/stats

# Test redirection
curl -I http://localhost:3000/goog

Security & Validation

Multi-Layer Security

  • Rate Limiting: Redis-backed per-IP throttling with configurable windows
  • Input Validation: Regex pattern matching + live URL reachability checks
  • XSS Prevention: Input sanitization middleware on all request bodies
  • Malicious URL Detection: Pattern-based screening (javascript:, <script, etc.)
  • Protocol Validation: HTTP/HTTPS only
  • Security Headers: Helmet.js in production
  • Custom Code Validation: Alphanumeric + -_ only, 3–20 characters

Response Patterns

Success (new URL)

{ "status": true, "message": "Short URL created successfully", "data": { ... } }

Success (existing URL)

{ "status": true, "message": "Short URL already exists", "data": { ... } }

Error

{ "status": false, "message": "URL is not accessible or invalid" }

Rate Limited

{ "status": false, "message": "Too many requests, please try again later" }

Configuration

Environment Variables

# Server (MONGO_URI is required — server exits on startup if missing)
NODE_ENV=development
PORT=3000
BASE_URL=http://localhost:3000

# Database (required)
MONGO_URI=mongodb://localhost:27017/redislink

# Cache
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
CACHE_TTL=86400

# Monitoring
LOG_LEVEL=info

Monitoring & Production Features

Health Monitoring

  • Real-time service status with connection monitoring
  • Database and Redis health tracking with retry counts
  • Server uptime and environment info
  • Graceful shutdown with full resource cleanup

Logging & Observability

  • Request Logging: Morgan middleware (dev format in development, combined in production)
  • Error Tracking: Centralized error handling with stack traces in dev mode
  • Connection Events: Database and Redis connection lifecycle logging
  • Click Analytics: Per-URL redirect counts tracked in MongoDB

Performance Benchmarks

  • URL Creation: ~50ms (cache miss) / ~5ms (cache hit)
  • URL Redirection: ~5ms (Redis cache hit)
  • Bulk (10 URLs): ~500ms (parallel processing)
  • Health Check: <2ms
  • Concurrent Connections: Supports 1000+ concurrent requests

Roadmap - Phase 3

  • Unit Test Suite: Jest + Supertest
  • Docker Containerization: Multi-stage production build
  • CI/CD Pipeline: GitHub Actions
  • Monitoring Dashboard: Grafana + Prometheus
  • Redis Password Auth: Secure Redis in production deployments

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors