https://github.com/largonarco/ratex
A scalable Rate Limiter Proxy API Service
https://github.com/largonarco/ratex
rate-limiter redis rediscluster
Last synced: 28 days ago
JSON representation
A scalable Rate Limiter Proxy API Service
- Host: GitHub
- URL: https://github.com/largonarco/ratex
- Owner: Largonarco
- Created: 2025-04-08T18:52:14.000Z (about 2 months ago)
- Default Branch: master
- Last Pushed: 2025-04-20T06:02:40.000Z (about 1 month ago)
- Last Synced: 2025-04-20T07:19:17.006Z (about 1 month ago)
- Topics: rate-limiter, redis, rediscluster
- Language: TypeScript
- Homepage:
- Size: 216 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# RateX API Gateway
RateX is a powerful API Gateway that provides rate limiting, request queuing, and proxy capabilities for your APIs. It supports multiple rate limiting strategies and allows you to manage multiple applications through a single gateway.
## HLD

These rate limiting servers would scale up and down depending upon load and these would communicate with a centralised Redis data store for scalabilty.
## Database Schema
At the moment the _Users_ and _Apps_ data strcutures are stored in Redis but in a real scenario they should alwayss be stored in an on-disk database for durability and to avoid data loss.
### Users
- Key: `user:` (Redis Hash)
- Fields:
- `id`: string (UUID)
- `email`: string
- `password`: string (hashed)
- `organisationName`: string
- `apiKey`: string (hashed)
- `createdAt`: string (timestamp)
- Associated Set: `user::apps`
- Stores App IDs (`app:`) associated with the user.### Apps
- Key: `app:` (Redis Hash)
- Fields:
- `id`: string (e.g., `app:`)
- `name`: string
- `baseUrl`: string (URL)
- `userId`: string (User's email)
- `rateLimit`: string (JSON representation of rate limit config: `strategy`, `window`, `requests`, potentially `burst`, `refillRate`, `leakRate`)
- `totalRequests` (Optional, inferred from stats endpoint): number### QueueService (Queued Requests)
- Key: `queue:` (Redis Sorted Set)
- Score: Timestamp of enqueueing
- Member: JSON string representing a Queued Request object.
- Queued Request Object Fields:
- `id`: string (e.g., `req::`)
- `appId`: string (ID of the target app, e.g., `app:`)
- `path`: string (Requested path)
- `method`: string (HTTP method)
- `headers`: object (Request headers)
- `body`: any (Request body, if applicable)
- `timestamp`: number (Enqueue timestamp)## Setup Instructions
1. Clone the repository
2. Install dependencies:
```bash
npm install
```3. Create a `.env` file with the following variables:
```
PORT=3000
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DB=0
JWT_SECRET=your_jwt_secret
```4. Start Redis server
```
docker run --name ratex-redis -p 6379:6379 -d redis
```5. Start the application:
```bash
npm start
```## Rate Limiting Strategies
Redis transactions (MULTI / EXEC) are used to implement ACID to some extent with optimistic concurrency control using WATCH. A simple queueing mechanism is used to queue requests that are rate limited to execute later. The implementation uses hash slots (`{strategy:key}`) to ensure atomic, isolated, and consistent operations even in a Redis cluster environment, preventing key migration issues and maintaining data consistency across nodes.
1. **Fixed Window**
- Simple window-based rate limiting
- Resets at fixed intervals
- Configuration:
```json
{
"strategy": "fixed_window",
"window": 60, // seconds
"requests": 100 // requests per window
}
```2. **Sliding Window**
- More accurate rate limiting that considers overlapping windows
- Configuration:
```json
{
"strategy": "sliding_window",
"window": 60,
"requests": 100
}
```3. **Token Bucket**
- Allows for burst traffic while maintaining average rate
- Configuration:
```json
{
"strategy": "token_bucket",
"window": 60,
"requests": 100,
"burst": 50,
"refillRate": 2
}
```4. **Leaky Bucket**
- Smooths out traffic spikes
- Configuration:
```json
{
"strategy": "leaky_bucket",
"window": 60,
"requests": 100,
"leakRate": 2
}
```5. **Sliding Log**
- Most accurate but memory-intensive
- Configuration:
```json
{
"strategy": "sliding_log",
"window": 60,
"requests": 100
}
```## API Endpoints
### Authentication (Single layer authentication using JWT)
#### POST /auth/login
- Logs in a user and sets a JWT cookie
- Request body:
```json
{
"email": "[email protected]",
"password": "password123"
}
```#### GET /auth/refresh
- Refreshes the JWT token
- Requires valid JWT cookie#### GET /auth/logout
- Logs out the user and clears the JWT cookie
- Requires valid JWT cookie### Users (Single layer authentication using JWT)
#### POST /users
- Creates a new user
- Request body:
```json
{
"email": "[email protected]",
"password": "password123",
"organisationName": "My Org"
}
```#### GET /users
- Returns user information
- Requires valid JWT and API key#### PUT /users
- Updates user information
- Requires valid JWT and API key
- Request body:
```json
{
"organisationName": "Updated Org Name"
}
```### Applications (Dual layer authentication using JWT and API KEY)
#### POST /apps
- Creates a new application to proxy
- Requires valid JWT and API key
- Request body:
```json
{
"name": "My API",
"baseUrl": "https://api.example.com",
"rateLimit": {
"strategy": "fixed_window",
"window": 60,
"requests": 100
}
}
```#### GET /apps
- Lists all applications for the user
- Requires valid JWT and API key#### GET /apps/:appId
- Gets application details
- Requires valid JWT and API key#### PUT /apps/:appId
- Updates application settings
- Requires valid JWT and API key
- Request body:
```json
{
"name": "Updated API Name",
"baseUrl": "https://new-api.example.com",
"rateLimit": {
"strategy": "sliding_window",
"window": 60,
"requests": 200
}
}
```#### DELETE /apps/:appId
- Deletes an application
- Requires valid JWT and API key#### GET /apps/:appId/stats
- Gets request statistics for an application
- Requires valid JWT and API key### Proxy
#### ANY /apis/:appId/\*
- Proxies requests to the target API
- Requires valid API key
- Rate limited based on application settings#### GET /apis/status/:requestId
- Checks the status of a queued request
- Requires valid API key## Example Usage
### 1. Register a User
```bash
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "password123",
"organisationName": "My Org"
}'
```### 2. Login
```bash
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "password123"
}'
```### 3. Create an Application
```bash
curl -X POST http://localhost:3000/apps \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"name": "My API",
"baseUrl": "https://api.example.com",
"rateLimit": {
"strategy": "fixed_window",
"window": 60,
"requests": 100
}
}'
```### 4. Make a Proxied Request
```bash
curl -X GET http://localhost:3000/apis/YOUR_APP_ID/endpoint \
```### 5. Check Request Status
```bash
curl -X GET http://localhost:3000/apis/status/YOUR_REQUEST_ID \
```