ESC
Type to search...
S
Soli Docs

RateLimiter Class

Sliding window rate limiter for API protection and abuse prevention. Prevent brute force attacks and ensure fair resource usage.

RateLimiter(key, limit, window_seconds)

Creates a new rate limiter instance for the given key.

Parameters
  • key (String) - Rate limit key (e.g., "ip:192.168.1.1" or "user:123")
  • limit (Int) - Maximum requests allowed in the window
  • window_seconds (Int) - Time window in seconds
Example
# Create a rate limiter for API access
let limiter = RateLimiter("api:user123", 100, 60)

limiter.allowed()

Checks if a request is allowed under the rate limit using sliding window algorithm.

Returns Bool - true if allowed, false if rate limited
Example
# Limit API calls to 100 per minute per IP
let limiter = RateLimiter("ip:" + req["headers"]["X-Forwarded-For"], 100, 60)
if !limiter.allowed() {
    return { "status": 429, "body": "Too Many Requests" }
}

limiter.throttle()

Returns the number of seconds until the next request is allowed.

Returns Int - Seconds to wait (0 if allowed immediately)

limiter.status()

Gets detailed rate limit status with remaining requests and reset time.

Returns Hash with keys: allowed, remaining, reset_in, limit, window
let limiter = RateLimiter("api:" + api_key, 1000, 3600)
let status = limiter.status()
println("Remaining: " + str(status["remaining"]) + "/" + str(status["limit"]))

limiter.headers()

Generates rate limit headers for HTTP responses.

Returns Hash with: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset

limiter.reset()

Resets the rate limit for this instance's key.

Returns Bool - true on success

Static Methods

RateLimiter.reset_all()

Resets all rate limit counters.

RateLimiter.cleanup()

Cleans up expired rate limit entries.

Helper Functions

rate_limiter_from_ip(req, limit, window_seconds)

Creates a RateLimiter instance based on client IP address (extracts from X-Forwarded-For or Remote-Addr).

Complete Example

# API middleware with rate limiting
def rate_limit_middleware(req)
    let ip = req["headers"]["X-Forwarded-For"] || req["headers"]["Remote-Addr"]
    let limiter = RateLimiter("api:" + ip, 100, 60)
    
    # Check rate limit (100 requests per minute)
    if !limiter.allowed() {
        let status = limiter.status()
        let headers = limiter.headers()
        
        return {
            "continue": false,
            "response": {
                "status": 429,
                "headers": headers,
                "body": json_stringify({
                    "error": "Rate limit exceeded",
                    "retry_after": status["reset_in"]
                })
            }
        }
    }
    
    { "continue": true, "request": req }
end