
- Updated `.env` and added `.env.test` for environment variables. - Introduced API documentation in `API_DOCUMENTATION.md`. - Added authentication setup guide in `AUTHENTICATION_SETUP.md`. - Implemented user authentication with JWT and email verification. - Created new routes for user management and form submissions. - Added middleware for API key authentication and error handling. - Set up Redis for rate limiting and notifications. - Removed obsolete files and configurations related to the previous Rust implementation.
165 lines
4.5 KiB
Markdown
165 lines
4.5 KiB
Markdown
# Rate Limiting Documentation
|
|
|
|
## Overview
|
|
|
|
This application now implements a scalable Redis-backed rate limiting system to protect against abuse and ensure fair usage of the form submission endpoints.
|
|
|
|
## Rate Limiting Strategy
|
|
|
|
The `/submit/:formUuid` endpoint is protected by three layers of rate limiting:
|
|
|
|
### 1. Strict Rate Limiter (First Layer)
|
|
|
|
- **Window**: 1 hour
|
|
- **Limit**: 50 requests per IP address across all forms
|
|
- **Purpose**: Prevents aggressive abuse from single IP addresses
|
|
- **Key**: `strict_ip:{ip_address}`
|
|
|
|
### 2. General Submission Rate Limiter (Second Layer)
|
|
|
|
- **Window**: 15 minutes
|
|
- **Limit**: 10 requests per IP address for any form submissions
|
|
- **Purpose**: Prevents rapid-fire submissions from legitimate users
|
|
- **Key**: `submit_ip:{ip_address}`
|
|
|
|
### 3. Form-Specific Rate Limiter (Third Layer)
|
|
|
|
- **Window**: 5 minutes
|
|
- **Limit**: 3 requests per IP address per specific form
|
|
- **Purpose**: Prevents spam on individual forms
|
|
- **Key**: `submit_form:{formUuid}:{ip_address}`
|
|
|
|
## Infrastructure
|
|
|
|
### Redis Configuration
|
|
|
|
#### Development Environment
|
|
|
|
- **Service**: `redis:7-alpine`
|
|
- **Port**: `6379`
|
|
- **Data Persistence**: Yes (Redis AOF)
|
|
- **Volume**: `redis_data:/data`
|
|
|
|
#### Production Environment
|
|
|
|
- **Service**: `redis:7-alpine`
|
|
- **Port**: `6380` (external, to avoid conflicts)
|
|
- **Data Persistence**: Yes (Redis AOF)
|
|
- **Volume**: `redis_data:/data`
|
|
- **Password Protection**: Configurable via `REDIS_PASSWORD`
|
|
- **Health Checks**: Enabled
|
|
|
|
### Environment Variables
|
|
|
|
```env
|
|
# Redis Configuration
|
|
REDIS_HOST=redis # Redis hostname (default: redis in Docker, localhost otherwise)
|
|
REDIS_PORT=6379 # Redis port (default: 6379)
|
|
REDIS_PASSWORD= # Optional Redis password (production recommended)
|
|
```
|
|
|
|
## Fallback Mechanism
|
|
|
|
If Redis is unavailable, the system automatically falls back to an in-memory rate limiter:
|
|
|
|
- **Graceful Degradation**: Application continues to function without Redis
|
|
- **Automatic Detection**: Detects Redis availability and switches accordingly
|
|
- **Logging**: Warns when falling back to memory store
|
|
- **Same Limits**: Maintains the same rate limiting rules
|
|
|
|
## Rate Limit Headers
|
|
|
|
When rate limits are applied, the following headers are returned:
|
|
|
|
- `RateLimit-Limit`: Maximum number of requests allowed
|
|
- `RateLimit-Remaining`: Number of requests remaining in window
|
|
- `RateLimit-Reset`: Time when the rate limit window resets
|
|
|
|
## Error Responses
|
|
|
|
When rate limits are exceeded, the API returns:
|
|
|
|
```json
|
|
{
|
|
"error": "Too many requests from this IP address. Please try again later."
|
|
}
|
|
```
|
|
|
|
The specific error message varies by rate limiter:
|
|
|
|
- **Strict**: "Too many requests from this IP address. Please try again later."
|
|
- **General**: "Too many form submissions from this IP address. Please try again later."
|
|
- **Form-Specific**: "Too many submissions for this form from your IP address. Please try again later."
|
|
|
|
## Deployment
|
|
|
|
### Starting Services
|
|
|
|
#### Development
|
|
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
#### Production
|
|
|
|
```bash
|
|
docker-compose -f docker-compose.prod.yml up -d
|
|
```
|
|
|
|
### Monitoring Redis
|
|
|
|
Check Redis connection:
|
|
|
|
```bash
|
|
docker exec -it formies-redis-1 redis-cli ping
|
|
```
|
|
|
|
View rate limiting keys:
|
|
|
|
```bash
|
|
docker exec -it formies-redis-1 redis-cli --scan --pattern "submit_*"
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Redis Security**: In production, always use password authentication
|
|
2. **Network Security**: Redis should not be exposed to public networks
|
|
3. **Data Persistence**: Redis data is persisted to handle container restarts
|
|
4. **Graceful Shutdown**: Application properly closes Redis connections on exit
|
|
|
|
## Performance
|
|
|
|
- **Scalability**: Redis-backed rate limiting scales across multiple application instances
|
|
- **Efficiency**: O(1) operations for rate limit checks
|
|
- **Memory Usage**: Efficient key expiration prevents memory leaks
|
|
- **High Availability**: Can be configured with Redis clustering for production
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Redis Connection Failed**
|
|
|
|
- Check if Redis container is running
|
|
- Verify environment variables
|
|
- Check Docker network connectivity
|
|
|
|
2. **Rate Limiting Not Working**
|
|
|
|
- Verify Redis connection in application logs
|
|
- Check if fallback to memory store is occurring
|
|
- Ensure proper IP address detection
|
|
|
|
3. **Performance Issues**
|
|
- Monitor Redis memory usage
|
|
- Check for connection pooling configuration
|
|
- Verify network latency between app and Redis
|
|
|
|
### Logs to Monitor
|
|
|
|
- Redis connection status
|
|
- Rate limiter fallback warnings
|
|
- Rate limit exceeded events
|
|
- Redis error messages
|