Rate Limit API Documentation
Overview
UVHTTP provides server-level rate limiting to prevent DDoS attacks and overload. The rate limiting feature can be enabled or disabled at compile time through macros.
Features
- Server-level rate limiting: All requests share the same rate limit counter
- Fixed window algorithm: A simple and efficient rate limiting algorithm
- IP whitelist: Supports an IP address whitelist that is exempt from rate limiting
- Zero overhead: Implemented via conditional compilation; no runtime overhead when disabled
- Configurable: Supports custom maximum request count and time window
Compile Configuration
Enable Rate Limiting (default)
make buildDisable Rate Limiting
Edit CMakeLists.txt, change the default value of option(UVHTTP_FEATURE_RATE_LIMIT ...) to OFF, then run:
make buildAPI Reference
Enable Rate Limiting
uvhttp_error_t uvhttp_server_enable_rate_limit(
uvhttp_server_t* server,
int max_requests,
int window_seconds
);Parameters:
server: The server instancemax_requests: Maximum number of requests allowed within the time window (range: 1-1000000)window_seconds: The time window in seconds (range: 1-86400)
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameter
Description:
- Implements rate limiting using the fixed window algorithm
- Rate limit state is embedded directly in the server structure, requiring no dynamic memory allocation
- All requests share the same rate limit counter (server-level rate limiting)
Example:
// At most 1000 requests per second
uvhttp_server_enable_rate_limit(server, 1000, 1);
// At most 6000 requests per minute
uvhttp_server_enable_rate_limit(server, 6000, 60);Disable Rate Limiting
uvhttp_error_t uvhttp_server_disable_rate_limit(uvhttp_server_t* server);Parameters:
server: The server instance
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameter
Example:
uvhttp_server_disable_rate_limit(server);Add an IP Whitelist Entry
uvhttp_error_t uvhttp_server_add_rate_limit_whitelist(
uvhttp_server_t* server,
const char* client_ip
);Parameters:
server: The server instanceclient_ip: The client IP address (e.g., "127.0.0.1")
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameterUVHTTP_ERROR_OUT_OF_MEMORY: Memory allocation failed
Example:
// The loopback address is not rate limited
uvhttp_server_add_rate_limit_whitelist(server, "127.0.0.1");
// The internal network address is not rate limited
uvhttp_server_add_rate_limit_whitelist(server, "10.0.0.1");Get Rate Limit Status
uvhttp_error_t uvhttp_server_get_rate_limit_status(
uvhttp_server_t* server,
const char* client_ip,
int* remaining,
uint64_t* reset_time
);Parameters:
server: The server instanceclient_ip: The client IP address (currently unused, reserved for future expansion)remaining: Remaining request count (output parameter)reset_time: Reset timestamp in milliseconds (output parameter)
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameter
Note:
- The current implementation uses server-level rate limiting; the
client_ipparameter is unused - The returned
remainingandreset_timeare server-level state
Example:
int remaining;
uint64_t reset_time;
uvhttp_server_get_rate_limit_status(server, "127.0.0.1", &remaining, &reset_time);
printf("Remaining requests: %d, reset time: %lu\n", remaining, reset_time);Reset a Client's Rate Limit State
uvhttp_error_t uvhttp_server_reset_rate_limit_client(
uvhttp_server_t* server,
const char* client_ip
);Parameters:
server: The server instanceclient_ip: The client IP address (currently unused, reserved for future expansion)
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameter
Note:
- The current implementation resets the rate limit counter for the entire server
- The
client_ipparameter is unused, reserved for future expansion
Example:
uvhttp_server_reset_rate_limit_client(server, "127.0.0.1");Clear All Rate Limit State
uvhttp_error_t uvhttp_server_clear_rate_limit_all(uvhttp_server_t* server);Parameters:
server: The server instance
Return value:
UVHTTP_OK: SuccessUVHTTP_ERROR_INVALID_PARAM: Invalid parameter
Example:
uvhttp_server_clear_rate_limit_all(server);Usage Examples
Basic Usage
#include "uvhttp.h"
int main() {
uv_loop_t* loop = uv_default_loop();
uvhttp_server_t* server = NULL;
uvhttp_server_new(loop, &server);
// Enable rate limiting: at most 1000 requests per second
uvhttp_server_enable_rate_limit(server, 1000, 1);
// Add a whitelist entry
uvhttp_server_add_rate_limit_whitelist(server, "127.0.0.1");
// Start the server
uvhttp_server_listen(server, "0.0.0.0", 8080);
uv_run(loop, UV_RUN_DEFAULT);
uvhttp_server_free(server);
return 0;
}Adjusting Rate Limit Dynamically
// Adjust rate limit parameters at runtime
void adjust_rate_limit(uvhttp_server_t* server, int new_max_requests) {
// Disable first
uvhttp_server_disable_rate_limit(server);
// Re-enable
uvhttp_server_enable_rate_limit(server, new_max_requests, 1);
}Rate Limit Response
When a request exceeds the rate limit, the server returns:
- Status code: 429 Too Many Requests
- Content-Type: text/plain
- Retry-After: 60 (suggests retrying after 60 seconds)
- Response body: "Too Many Requests"
Design Notes
Server-Level Rate Limiting
The current implementation uses server-level rate limiting, where all requests share the same rate limit counter. This design is suitable for:
- DDoS protection: Limits the total request volume the server receives
- Resource protection: Prevents the server from crashing due to overload
- Simple and efficient: No need to maintain per-client state
Why Not Client-Level?
Client-level rate limiting requires:
- Maintaining independent rate limit state for each client
- Storing client state in a hash table
- Periodically cleaning up expired client state
- More complex memory management
For DDoS protection scenarios, server-level rate limiting is sufficient, and:
- Better performance: No hash table lookups
- Less memory: Only a single counter
- Simpler implementation: Easier to maintain code
Future Expansion
If client-level rate limiting is needed, you could consider:
- Using the
uthashlibrary to store client state - Implementing a sliding window algorithm
- Adding client state expiration
- Providing finer-grained rate limit control
Error Codes
Rate-limit-related error codes:
UVHTTP_ERROR_RATE_LIMIT_EXCEEDED = -550 // Rate limit exceededPerformance Considerations
- Time complexity: O(1) - fixed window algorithm
- Space complexity: O(1) - maintains only a single counter
- Throughput: ~819,000 checks/second
- Average latency: ~1.2 microseconds
- Memory usage: 12 bytes (rate limit context)
- Overhead: Minimal, only simple counting and comparison operations
Performance Optimizations
- Zero memory allocation: Rate limit state is embedded directly in the server structure, requiring no dynamic memory allocation
- Cache-friendly: All hot data resides in the same cache line, reducing cache misses
- No pointer dereferencing: Direct field access in the struct is faster than pointer access
- Compile-time optimization: Implemented via conditional compilation; no runtime overhead when disabled
Best Practices
Configure rate limit parameters sensibly
- Set
max_requestsbased on server performance - Set
window_secondsbased on business requirements - Avoid overly strict rate limiting that affects normal users
- Set
Use the whitelist
- Add trusted IP addresses to the whitelist
- Include monitoring systems, internal services, and similar
- Avoid rate limiting affecting critical services
Monitor rate limit status
- Periodically check
remainingandreset_time - Log rate-limit-triggered events
- Adjust parameters based on actual conditions
- Periodically check
Graceful degradation
- Return clear error messages when the rate limit is exceeded
- Provide the
Retry-Afterheader - Consider implementing a cache layer to reduce server load