express-limiter-pro
Version:
A TypeScript library for safe display and sanitization to prevent XSS attacks.
371 lines (262 loc) โข 9.43 kB
Markdown
A comprehensive TypeScript library for Express.js applications that provides advanced rate limiting, authentication security, and configuration management. Protect your APIs from brute force attacks, DDoS attempts, and unauthorized access with intelligent rate limiting rules and dynamic configuration.
- ๐ก๏ธ **Multi-tier Rate Limiting** - Different limits for API, authentication, and sensitive operations
- ๐ **2FA Protection** - Special rate limiting for two-factor authentication endpoints
- โก **High Performance** - Built with TypeScript and optimized for production
- ๐ฏ **Intelligent Detection** - Header-based and path-based endpoint recognition
- ๐ง **Dynamic Configuration** - Event-driven configuration management with hot reloading
- ๐ **Full TypeScript Support** - Complete type definitions and IntelliSense support
- ๐งช **Battle Tested** - 80%+ test coverage with comprehensive test suite
- [Installation](
- [Quick Start](
- [API Reference](
- [Configuration](
- [Rate Limiting Rules](
- [Examples](
- [Error Handling](
- [TypeScript Support](
- [Contributing](
- [License](
```bash
npm install express-limiter-pro
yarn add express-limiter-pro
pnpm add express-limiter-pro
```
This package requires Express.js as a peer dependency:
```bash
npm install express
```
```typescript
import express from 'express';
import { configureRateLimits, configManager, ConfigSource } from 'express-limiter-pro';
const app = express();
// Set up configuration source
const configSource: ConfigSource = async () => ({
accessTokenSecret: process.env.ACCESS_TOKEN_SECRET || 'default-secret',
isDevelopment: process.env.NODE_ENV === 'development'
});
configManager.setConfigSource(configSource);
// Configure rate limiting
configureRateLimits(app);
// Load configuration
await configManager.loadConfig();
app.listen(3000);
```
Configures rate limiting middleware for an Express application with predefined rules for different endpoint types.
- `app` - Express Application instance
1. **API Endpoints** (`/api`, `/api/v1`)
- Uses general API rate limiter
- Applied to all API routes
2. **Authentication Endpoints** (`/api/auth`, `/api/v1/auth`)
- Uses stricter authentication rate limiter
- Applied when path includes: `/login`, `/register`, `/authenticate`
3. **Sensitive Operations** (`/api`)
- Uses most restrictive sensitive operations limiter
- Applied to:
- Paths containing `/2fa`
- Requests with specific API endpoint headers:
- `auth:2fa-setup`
- `auth:2fa-enable`
- `auth:2fa-disable`
- `auth:2fa-verify`
- `Error` - If rate limiting configuration fails
Sets the configuration source function.
```typescript
const source: ConfigSource = async () => ({
accessTokenSecret: 'your-secret',
isDevelopment: false
});
configManager.setConfigSource(source);
```
Directly sets the configuration and emits a `configAvailable` event.
```typescript
configManager.setConfig({
accessTokenSecret: 'direct-secret',
isDevelopment: true
});
```
Returns the current configuration or `undefined` if not set.
```typescript
const currentConfig = configManager.getConfig();
if (currentConfig) {
console.log('Current secret:', currentConfig.accessTokenSecret);
}
```
Loads configuration from the configured source.
```typescript
try {
const config = await configManager.loadConfig();
console.log('Config loaded:', config);
} catch (error) {
console.error('Failed to load config:', error);
}
```
```typescript
// Listen for configuration changes
configManager.on('configAvailable', (config: TokenSecret) => {
console.log('New config available:', config);
});
// Remove event listener
configManager.off('configAvailable', handler);
// Emit custom events
configManager.emit('customEvent', data);
```
```typescript
interface TokenSecret {
accessTokenSecret: string;
isDevelopment: boolean;
}
```
```typescript
type ConfigSource = () => Promise<TokenSecret>;
```
```typescript
interface RateLimitRule {
paths: string[];
limiter: RequestHandler;
condition?: (req: Request) => boolean;
}
```
Rate limiting rules are applied in the following order:
1. **General API Routes** - Broadest scope, lowest restrictions
2. **Authentication Routes** - Medium restrictions for login/register
3. **Sensitive Operations** - Highest restrictions for 2FA operations
Rules can include optional conditions that determine when the limiter should be applied:
```typescript
{
paths: ['/api/auth'],
limiter: authLimiter,
condition: (req) => req.path.includes('/login')
}
```
The module checks for API endpoint headers to identify sensitive operations:
- Primary header: `API_ENDPOINT_HEADER`
- Fallback: Lowercase version of the header
- Supported values: `auth:2fa-setup`, `auth:2fa-enable`, `auth:2fa-disable`, `auth:2fa-verify`
```typescript
import express from 'express';
import { configureRateLimits, configManager } from 'express-limiter-pro';
const app = express();
// Configure from environment
configManager.setConfigSource(async () => ({
accessTokenSecret: process.env.JWT_SECRET || 'fallback-secret',
isDevelopment: process.env.NODE_ENV !== 'production'
}));
// Apply rate limiting
configureRateLimits(app);
// Load and use configuration
configManager.loadConfig().then(config => {
console.log(`Server starting in ${config.isDevelopment ? 'development' : 'production'} mode`);
});
```
```typescript
import { configManager } from 'express-limiter-pro';
// Set up event listener
configManager.on('configAvailable', (config) => {
console.log('Configuration updated:', {
hasSecret: !!config.accessTokenSecret,
isDevelopment: config.isDevelopment
});
});
// Dynamic configuration source
configManager.setConfigSource(async () => {
const response = await fetch('/api/config');
return response.json();
});
await configManager.loadConfig();
```
```typescript
import express from 'express';
import rateLimit from 'express-rate-limit';
const app = express();
// You would need to implement these limiter functions
const customApiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100
});
// Then configure with your custom limiters
configureRateLimits(app);
```
The module throws `ConfigNotFoundException` in these scenarios:
- Config source not set when `loadConfig()` is called
- Error occurs while loading configuration from source
```typescript
import { ConfigNotFoundException } from './errors/error';
try {
await configManager.loadConfig();
} catch (error) {
if (error instanceof ConfigNotFoundException) {
console.error('Configuration error:', error.message);
}
}
```
If rate limiting configuration fails, the `configureRateLimits` function will:
1. Log the error using the internal logger
2. Re-throw the error for handling by the application
```typescript
try {
configureRateLimits(app);
} catch (error) {
console.error('Failed to set up rate limiting:', error);
process.exit(1);
}
```
This module is written in TypeScript and includes full type definitions. All interfaces and types are exported for use in your application:
```typescript
import {
TokenSecret,
ConfigSource,
RateLimitRule
} from 'express-limiter-pro';
```
The configuration manager ensures type safety through:
- Strict typing of configuration objects
- Promise-based async operations with proper error handling
- Event emitter with typed event handlers
- `express` (^4.17.0) - Express.js web framework (peer dependency)
- `express-rate-limit` (^8.0.1) - Rate limiting middleware
- `jsonwebtoken` (^9.0.2) - JWT token handling
### Built With
- **TypeScript 5.8+** - Full type safety and modern JavaScript features
- **Node.js 14+** - Modern Node.js runtime support
- **Jest** - Comprehensive testing framework
- **ESLint** - Code quality and consistency