60 lines
1.9 KiB
TypeScript
60 lines
1.9 KiB
TypeScript
|
|
import rateLimit from 'express-rate-limit'
|
||
|
|
import { getRateLimit } from '../config/env'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Skip rate limiting for successful requests from localhost (development)
|
||
|
|
*/
|
||
|
|
const skipLocalhost = (req: any): boolean => {
|
||
|
|
return req.socket?.remoteAddress?.includes('127.0.0.1') ||
|
||
|
|
req.socket?.remoteAddress?.includes('::1') ||
|
||
|
|
req.ip?.includes('127.0.0.1') ||
|
||
|
|
req.ip?.includes('::1')
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get rate limit values from env vars (with defaults)
|
||
|
|
const WEBHOOK_LIMIT = getRateLimit('RATE_LIMIT_WEBHOOK', 10)
|
||
|
|
const HEALTH_LIMIT = getRateLimit('RATE_LIMIT_HEALTH', 30)
|
||
|
|
const DEFAULT_LIMIT = getRateLimit('RATE_LIMIT_DEFAULT', 60)
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Webhook limiter: 10 requests per minute per IP (configurable via RATE_LIMIT_WEBHOOK)
|
||
|
|
* RevenueCat retries are spaced minutes apart, so this is generous
|
||
|
|
*/
|
||
|
|
export const webhookLimiter = rateLimit({
|
||
|
|
windowMs: 60 * 1000, // 1 minute
|
||
|
|
max: WEBHOOK_LIMIT,
|
||
|
|
standardHeaders: true,
|
||
|
|
legacyHeaders: false,
|
||
|
|
skipSuccessfulRequests: true,
|
||
|
|
keyGenerator: (req) => req.ip || req.socket?.remoteAddress || 'unknown',
|
||
|
|
skip: (req) => skipLocalhost(req),
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Health limiter: 30 requests per minute per IP (configurable via RATE_LIMIT_HEALTH)
|
||
|
|
* Allows frequent health checks without abuse
|
||
|
|
*/
|
||
|
|
export const healthLimiter = rateLimit({
|
||
|
|
windowMs: 60 * 1000, // 1 minute
|
||
|
|
max: HEALTH_LIMIT,
|
||
|
|
standardHeaders: true,
|
||
|
|
legacyHeaders: false,
|
||
|
|
skipSuccessfulRequests: true,
|
||
|
|
keyGenerator: (req) => req.ip || req.socket?.remoteAddress || 'unknown',
|
||
|
|
skip: (req) => skipLocalhost(req),
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Default/API limiter: 60 requests per minute per IP (configurable via RATE_LIMIT_DEFAULT)
|
||
|
|
* For future authenticated routes
|
||
|
|
*/
|
||
|
|
export const defaultLimiter = rateLimit({
|
||
|
|
windowMs: 60 * 1000, // 1 minute
|
||
|
|
max: DEFAULT_LIMIT,
|
||
|
|
standardHeaders: true,
|
||
|
|
legacyHeaders: false,
|
||
|
|
skipSuccessfulRequests: true,
|
||
|
|
keyGenerator: (req) => req.ip || req.socket?.remoteAddress || 'unknown',
|
||
|
|
skip: (req) => skipLocalhost(req),
|
||
|
|
})
|