### Run Basic Rate Limiter Example (Crystal) Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Demonstrates the basic usage of the rate limiter. This example is written in Crystal and can be executed from the command line after navigating to the examples directory. ```bash cd examples crystal run basic_usage.cr ``` -------------------------------- ### Composable Limiters Example (Crystal) Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Illustrates how to combine multiple independent rate limiters with short-circuit evaluation. This Crystal code example is located in the examples directory. ```crystal # Placeholder for composable_limiters.cr content # This file demonstrates combining multiple limiters. ``` -------------------------------- ### Status and Reset Operations Example (Crystal) Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Explains how to check the status of the rate limiter and perform reset operations. This Crystal example is part of the project's usage demonstrations. ```crystal # Placeholder for status_and_reset.cr content # This file demonstrates checking status and resetting the limiter. ``` -------------------------------- ### Multiple Independent Rate Limiters in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Illustrates how to create and use multiple independent `RateLimiter` instances for different purposes (e.g., per user, per IP, per user+endpoint) and combine their checks. The example uses `any?` for short-circuit evaluation. ```crystal require "rate_limiter" # Create independent rate limiters for different purposes user_rate_limiter = RateLimiter.new(30, 3600) # 30 per hour per user ip_rate_limiter = RateLimiter.new(100, 3600) # 100 per hour per IP endpoint_rate_limiter = RateLimiter.new(10, 60) # 10 per minute per user+endpoint # Check individual limits username = "john_doe" ip_address = "192.168.1.1" endpoint = "/api/notes" user_allowed = user_rate_limiter.allow?(username) ip_allowed = ip_rate_limiter.allow?(ip_address) endpoint_allowed = endpoint_rate_limiter.allow?("#{username}::#{endpoint}") # Apply ALL limits with short-circuit evaluation request_allowed = [user_allowed, ip_allowed, endpoint_allowed].any? if request_allowed puts "Request allowed by all rate limiters" else puts "Request blocked by one or more rate limiters" end ``` -------------------------------- ### Install Rate Limiter Crystal Shard Source: https://context7.com/ralsina/rate_limiter/llms.txt Instructions for adding the Rate Limiter library to your Crystal project's dependencies using the shard.yml file and installing it. ```yaml dependencies: rate_limiter: github: ralsina/rate_limiter ``` ```bash shards install ``` -------------------------------- ### Sliding Window Rate Limiter Example (Crystal) Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Shows the implementation of a sliding window behavior for rate limiting. This Crystal example is part of the project's comprehensive usage demonstrations. ```crystal # Placeholder for sliding_window.cr content # This file demonstrates sliding window rate limiting. ``` -------------------------------- ### Thread Safety Rate Limiter Example (Crystal) Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Demonstrates how the rate limiter handles concurrent access from multiple threads, ensuring thread safety. This Crystal code is available in the examples directory. ```crystal # Placeholder for thread_safety.cr content # This file demonstrates thread-safe access to the rate limiter. ``` -------------------------------- ### Sliding Window Algorithm Behavior Source: https://context7.com/ralsina/rate_limiter/llms.txt Illustrates the behavior of the sliding window algorithm in the Rate Limiter. This example shows how requests are allowed and blocked over time as the window slides, demonstrating smooth enforcement rather than hard boundaries. It includes phases for filling the window, exceeding the limit, and waiting for requests to become available again. ```crystal require "rate_limiter" # Create limiter: 3 requests per 2 seconds limiter = RateLimiter.new(3, 2) user = "charlie" # Phase 1: Fill the window quickly puts "Making 3 requests rapidly..." 3.times do |i| allowed = limiter.allow?(user) puts "Request #{i + 1}: #{allowed ? "ALLOWED" : "BLOCKED"}" sleep(0.1) # Small delay between requests end # Phase 2: Try to exceed (should be blocked) puts "\nTrying to exceed limit..." extra = limiter.allow?(user) puts "Extra request: #{extra ? "ALLOWED" : "BLOCKED"}" # BLOCKED # Phase 3: Wait for partial window slide puts "\nWaiting 1.5 seconds..." sleep(1.5) still_blocked = limiter.allow?(user) puts "After 1.5s: #{still_blocked ? "ALLOWED" : "BLOCKED"}" # Still BLOCKED (not enough time) # Phase 4: Wait for window to slide enough puts "\nWaiting another 1 second (2.5s total)..." sleep(1) allowed_again = limiter.allow?(user) puts "After 2.5s total: #{allowed_again ? "ALLOWED" : "BLOCKED"}" # ALLOWED # Check final status final = limiter.status(user) puts "\nFinal status:" puts " Remaining: #{final.remaining}" puts " Total in window: #{final.total_requests}" ``` -------------------------------- ### Concurrent Operations with Rate Limiter Source: https://context7.com/ralsina/rate_limiter/llms.txt Demonstrates how to use the Rate Limiter with concurrent operations (fibers) to control access. It shows spawning multiple fibers that attempt to use the limiter and collecting the results to verify the limit enforcement. This example highlights the thread-safe nature of the limiter. ```crystal require "rate_limiter" limiter = RateLimiter.new(10, 60) # Example: 10 requests per 60 seconds user = "test_user" # Channel to collect results from concurrent operations results = Channel(Bool).new # Spawn 20 fibers trying to access the same limiter concurrently 20.times do |i| spawn do allowed = limiter.allow?(user) results.send(allowed) end end # Collect all results allowed_count = 0 blocked_count = 0 20.times do if results.receive allowed_count += 1 else blocked_count += 1 end end puts "Results from 20 concurrent requests:" puts " Allowed: #{allowed_count}" # => Example output: 10 puts " Blocked: #{blocked_count}" # => Example output: 10 puts " Expected: 10 allowed, 10 blocked (limit is 10)" # Verify the limiter state is consistent status = limiter.status(user) puts "Final state - Total requests recorded: #{status.total_requests}" # => Example output: 10 ``` -------------------------------- ### Install Rate Limiter Crystal Shard Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Add the rate_limiter shard to your Crystal project's shard.yml file to include it as a dependency. ```yaml dependencies: rate_limiter: github: ralsina/rate_limiter ``` -------------------------------- ### Get Detailed Rate Limit Status with RateLimiter#check Source: https://context7.com/ralsina/rate_limiter/llms.txt Illustrates using the `check` method to obtain a `RateLimitResult` struct, providing detailed information like remaining requests, total requests in the window, and the reset time. This method also consumes a request. ```crystal require "rate_limiter" limiter = RateLimiter.new(10, 60) # 10 requests per minute result = limiter.check("user123") # Access detailed rate limit information puts "Allowed: #{result.allowed?}" # true or false puts "Rate Limited: #{result.rate_limited?}" # inverse of allowed? puts "Remaining: #{result.remaining}" # requests left in window puts "Total Requests: #{result.total_requests}" # requests made in window puts "Reset Time: #{result.reset_time}" # when limit resets (Time) # Use in API responses with JSON serialization response_data = result.to_h # => {"allowed" => true, "remaining" => 9, "reset_time" => 1234567890, "total_requests" => 1} # Practical usage pattern result = limiter.check("user123") if result.allowed? puts "Processing request. You have #{result.remaining} requests remaining." else seconds_until_reset = (result.reset_time - Time.utc).total_seconds.to_i puts "Rate limited. Try again in #{seconds_until_reset} seconds." end ``` -------------------------------- ### Get Detailed Rate Limiter Results in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Shows how to use the `check` method to obtain detailed information about a rate limit status, including whether the request is allowed, remaining requests, and reset time. This method also consumes a request. ```crystal rate_limiter = RateLimiter.new(10, 60) # 10 requests per minute result = rate_limiter.check("user123") puts "Allowed: #{result.allowed?}" puts "Remaining: #{result.remaining}" puts "Total requests: #{result.total_requests}" puts "Reset time: #{result.reset_time}" ``` -------------------------------- ### Create New Rate Limiter Instances Source: https://context7.com/ralsina/rate_limiter/llms.txt Demonstrates how to instantiate `RateLimiter` objects with different maximum requests and time windows for various use cases like API limits, burst limits, and IP-based limits. ```crystal require "rate_limiter" # Create rate limiters for different use cases # Basic rate limiter: 30 requests per hour api_limiter = RateLimiter.new(30, 3600) # Short burst limiter: 5 requests per minute burst_limiter = RateLimiter.new(5, 60) # AI endpoint limiter: 50 requests per hour (expensive operations) ai_limiter = RateLimiter.new(50, 3600) # IP-based limiter: 100 requests per hour per IP address ip_limiter = RateLimiter.new(100, 3600) # Sliding window demo: 3 requests per 2 seconds demo_limiter = RateLimiter.new(3, 2) ``` -------------------------------- ### Advanced Rate Limiter Strategies in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Demonstrates advanced usage patterns for rate limiting, including per-user, per-IP, per-endpoint, and per-user+endpoint strategies. It shows how to aggregate checks from multiple limiters. ```crystal # Per user rate limiting user_limiter = RateLimiter.new(50, 3600) # 50 requests per hour per user # Per IP rate limiting ip_limiter = RateLimiter.new(200, 3600) # 200 requests per hour per IP # Per endpoint rate limiting endpoint_limiter = RateLimiter.new(20, 60) # 20 requests per minute per endpoint # Per user + endpoint rate limiting user_endpoint_limiter = RateLimiter.new(10, 60) # 10 requests per minute per user+endpoint # Check request (example: user trying to access API) username = "alice" ip = "10.0.0.1" endpoint = "/api/create_note" # Check all applicable rate limits limits = [ user_limiter.allow?(username), ip_limiter.allow?(ip), endpoint_limiter.allow?(endpoint), user_endpoint_limiter.allow?("#{username}::#{endpoint}") ] if limits.any? # Request is allowed by all rate limiters process_request(username, ip, endpoint) else # Request exceeds at least one rate limit render_error("Rate limit exceeded") end ``` -------------------------------- ### Basic Rate Limiter Usage in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Demonstrates the fundamental usage of the RateLimiter class to create a limiter and check if a request is allowed for a given key. It requires the 'rate_limiter' library to be required. ```crystal require "rate_limiter" # Create a rate limiter: 30 requests per hour rate_limiter = RateLimiter.new(30, 3600) # Check if a request is allowed if rate_limiter.allow?("user123") # Process the request puts "Request allowed" else # Reject the request puts "Rate limit exceeded" end ``` -------------------------------- ### Check Request Allowance with RateLimiter#allow? Source: https://context7.com/ralsina/rate_limiter/llms.txt Shows how to use the `allow?` method to determine if a request should be permitted based on the defined rate limits. It returns a boolean and consumes a request if allowed. Ideal for simple pass/fail checks. ```crystal require "rate_limiter" # Create a rate limiter: 5 requests per minute limiter = RateLimiter.new(5, 60) user = "alice" # Basic usage pattern if limiter.allow?(user) puts "Request allowed - processing..." # Process the request else puts "Rate limit exceeded - rejecting request" # Return 429 Too Many Requests end # Example: Making multiple requests 6.times do |i| allowed = limiter.allow?(user) status = allowed ? "ALLOWED" : "BLOCKED" puts "Request #{i + 1}: #{status}" end # Output: # Request 1: ALLOWED # Request 2: ALLOWED # Request 3: ALLOWED # Request 4: ALLOWED # Request 5: ALLOWED # Request 6: BLOCKED ``` -------------------------------- ### RateLimiter Methods Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Core methods for initializing and interacting with the RateLimiter instance. ```APIDOC ## POST /RateLimiter/new ### Description Initializes a new rate limiter instance with a defined quota and time window. ### Method POST ### Parameters #### Request Body - **max_requests** (Int32) - Required - Maximum number of requests allowed in the window. - **window_seconds** (Int32) - Required - The duration of the sliding window in seconds. --- ## GET /RateLimiter/allow ### Description Checks if a request is allowed for a specific key and consumes one request unit if permitted. ### Method GET ### Parameters #### Query Parameters - **key** (String) - Required - The identifier for the user, IP, or endpoint. ### Response #### Success Response (200) - **allowed** (Bool) - Returns true if the request is within the limit, false otherwise. --- ## GET /RateLimiter/check ### Description Performs a check on the rate limit and returns a detailed result object containing status and metadata. ### Method GET ### Parameters #### Query Parameters - **key** (String) - Required - The identifier for the user, IP, or endpoint. ### Response #### Success Response (200) - **allowed?** (Bool) - Whether the request is allowed. - **remaining** (Int32) - Number of requests remaining in the current window. - **reset_time** (Time) - The timestamp when the window resets. - **total_requests** (Int32) - Total capacity of the window. ``` -------------------------------- ### Compose Multiple Rate Limiters in Crystal Source: https://context7.com/ralsina/rate_limiter/llms.txt Shows how to combine multiple independent rate limiters using strict or permissive logic. This allows for granular control over different dimensions like users, IPs, and specific endpoints. ```crystal require "rate_limiter" user_limiter = RateLimiter.new(30, 3600) ip_limiter = RateLimiter.new(100, 3600) endpoint_limiter = RateLimiter.new(10, 60) username = "john_doe" ip_address = "192.168.1.1" endpoint = "/api/notes" def allow_request_strict?(user_limiter, ip_limiter, endpoint_limiter, username, ip, endpoint) limits = [ user_limiter.allow?(username), ip_limiter.allow?(ip), endpoint_limiter.allow?("#{username}::#{endpoint}") ] limits.all? end def allow_request_permissive?(user_limiter, ip_limiter, endpoint_limiter, username, ip, endpoint) limits = [ user_limiter.allow?(username), ip_limiter.allow?(ip), endpoint_limiter.allow?("#{username}::#{endpoint}") ] limits.any? end ``` -------------------------------- ### Implement Tiered Rate Limiting in Crystal Source: https://context7.com/ralsina/rate_limiter/llms.txt Explains how to apply different rate limits to specific categories of endpoints, such as expensive AI operations versus standard API requests. This ensures that high-cost operations do not block general service availability. ```crystal require "rate_limiter" user_limiter = RateLimiter.new(500, 3600) ai_limiter = RateLimiter.new(50, 3600) def allow_request?(user_limiter, ai_limiter, user_id, endpoint) is_ai_endpoint = endpoint.starts_with?("/api/v1/ai/") limits = [] of Bool limits << user_limiter.allow?(user_id) if is_ai_endpoint limits << ai_limiter.allow?(user_id) end limits.all? end ``` -------------------------------- ### Check Rate Limiter Status in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Explains how to check the current status of a rate limiter using the `check` method, which provides details like remaining requests and reset time. Note that `check` also consumes a request. ```crystal limiter = RateLimiter.new(5, 60) # 5 requests per minute # Check current status (note: check() does consume a request) result = limiter.check("user123") if result.allowed? puts "User has #{result.remaining} requests remaining" else puts "User is rate limited until #{result.reset_time}" end ``` -------------------------------- ### RateLimitResult Struct Usage and Headers Source: https://context7.com/ralsina/rate_limiter/llms.txt Explains the `RateLimitResult` struct, which provides detailed information about a rate limit check. It covers accessing properties like `allowed?`, `remaining`, and `reset_time`, and demonstrates how to convert the result to a hash for use in HTTP response headers. ```crystal require "rate_limiter" limiter = RateLimiter.new(10, 60) # Get a result from check result = limiter.check("user123") # Available properties result.allowed? # => Bool - whether request is allowed result.rate_limited? # => Bool - inverse of allowed? (true when blocked) result.remaining # => Int32 - requests remaining in window result.total_requests # => Int32 - total requests made in current window result.reset_time # => Time - when the rate limit window resets # Convert to hash for JSON API responses hash = result.to_h # Returns: { "allowed" => true, "remaining" => 9, "reset_time" => 1234567890, "total_requests" => 1 } # Example values # Example: Building rate limit headers for HTTP responses def rate_limit_headers(result : RateLimitResult) { "X-RateLimit-Limit" => "10", "X-RateLimit-Remaining" => result.remaining.to_s, "X-RateLimit-Reset" => result.reset_time.to_unix.to_s } end headers = rate_limit_headers(result) puts headers # => Example output: {"X-RateLimit-Limit" => "10", "X-RateLimit-Remaining" => "9", "X-RateLimit-Reset" => "1234567890"} ``` -------------------------------- ### Check Rate Limit Status Without Consumption using RateLimiter#status Source: https://context7.com/ralsina/rate_limiter/llms.txt Demonstrates the `status` method, which returns the current rate limit status for a key without consuming a request. This is useful for displaying quota information or checking limits non-intrusively. ```crystal require "rate_limiter" limiter = RateLimiter.new(5, 60) # Make some requests 3.times { limiter.allow?("user123") } # Check status without consuming a request status = limiter.status("user123") puts "Current status for user:" puts " Allowed to make request: #{status.allowed?}" puts " Remaining requests: #{status.remaining}" puts " Total requests in window: #{status.total_requests}" puts " Reset time: #{status.reset_time}" # For users with no history, status returns full quota new_user_status = limiter.status("new_user") puts "New user remaining: #{new_user_status.remaining}" # => 5 (full quota) ``` -------------------------------- ### Reset Rate Limiter Data in Crystal Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Demonstrates how to reset the rate limiting data. `reset!` clears all data for all keys, while `reset_key!` clears data for a specific key. ```crystal limiter = RateLimiter.new(10, 60) # Reset all data limiter.reset! # Reset data for a specific key limiter.reset_key!("user123") ``` -------------------------------- ### Management Methods Source: https://github.com/ralsina/rate_limiter/blob/main/README.md Administrative methods for resetting rate limit data. ```APIDOC ## DELETE /RateLimiter/reset ### Description Clears all rate limiting data stored in the instance. ### Method DELETE --- ## DELETE /RateLimiter/reset_key ### Description Resets the rate limit data specifically for a provided key. ### Method DELETE ### Parameters #### Query Parameters - **key** (String) - Required - The identifier to reset. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.