### Correct Cluster Setup with Shared Storage Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/distributed-ratelimiting.md Example JSON configuration demonstrating a correct cluster setup for distributed rate limiting. All instances must share the same storage configuration and rate limit definitions. ```json { "storage": { "module": "file", "root": "/var/lib/caddy/rate_limit_state" }, "handler": "rate_limit", "distributed": {}, "rate_limits": { "api_limit": { "key": "{http.request.remote.host}", "window": "1m", "max_events": 1000 } } } ``` -------------------------------- ### Static Rate Limit Example (JSON and Caddyfile) Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Configures a static rate limit zone named 'static_example' allowing 100 GET requests per minute across all clients, with a matcher set applied. This example is shown in both JSON and Caddyfile formats. ```json { "handler": "rate_limit", "rate_limits": { "static_example": { "match": [ { "method": ["GET"] } ], "window": "1m", "max_events": 100 } } } ``` ```caddyfile rate_limit { zone static_example { match { method GET } window 1m events 100 } } ``` -------------------------------- ### JSON Configuration for RateLimit Zone Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ratelimit.md Example of how to configure a rate limit zone using JSON. This example sets up a zone named 'zone_name' that applies to GET and POST requests, uses the client's host as the key, and allows 100 events per minute with IPv6 prefix masking. ```json { "zone_name": { "match": [ {"method": ["GET", "POST"]} ], "key": "{http.request.remote.host}", "window": "1m", "max_events": 100, "ipv4_prefix": 0, "ipv6_prefix": 64 } } ``` -------------------------------- ### Example Rate Limit Configuration Metrics Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Shows example metric series for caddy_rate_limit_config, illustrating different zone configurations. ```text caddy_rate_limit_config{zone="api",max_events="1000",window="1m0s",ipv4_prefix="0",ipv6_prefix="64"} 1 caddy_rate_limit_config{zone="anonymous",max_events="100",window="1m0s",ipv4_prefix="24",ipv6_prefix="0"} 1 ``` -------------------------------- ### Example Usage of ServeHTTP Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Demonstrates how the ServeHTTP method is invoked within the Caddy framework. Direct invocation is uncommon; this example shows the typical parameters and error handling flow. Ensure a valid `caddyhttp.Handler` is passed as the `next` argument. ```go // This is called automatically by Caddy. Direct invocation is uncommon. handler := &Handler{ /* ... */ } w := responseWriter r := httpRequest nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { w.WriteHeader(200) return nil }) err := handler.ServeHTTP(w, r, nextHandler) if err != nil { // Handle rate limit error or next handler error } ``` -------------------------------- ### Rate Limit Matcher Example (JSON) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/types.md An example of how to define request matchers for a rate limit zone using JSON configuration. This allows specifying conditions like HTTP method or host for applying rate limits. ```json "match": [ { "method": ["GET", "POST"], "host": "api.example.com" } ] ``` -------------------------------- ### JSON Rate Limiting Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Configure static and dynamic rate limits using JSON. This example sets up a static limit for GET requests and a dynamic limit based on the client's IP address. ```json { "apps": { "http": { "servers": { "demo": { "listen": [":80"], "routes": [ { "handle": [ { "handler": "rate_limit", "rate_limits": { "static_example": { "match": [ {"method": ["GET"]} ], "key": "static", "window": "1m", "max_events": 100 }, "dynamic_example": { "key": "{http.request.remote.host}", "window": "5s", "max_events": 2 } }, "distributed": {}, "log_key": true }, { "handler": "static_response", "body": "I'm behind the rate limiter!" } ] } ] } } } } } ``` -------------------------------- ### Caddyfile Configuration for RateLimit Zone Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ratelimit.md Example of configuring a rate limit zone using Caddyfile syntax. This defines a zone 'my_zone' with similar settings to the JSON example: matching GET/POST requests, using remote host as key, 100 events per minute, and IPv6 prefix masking. ```caddyfile zone my_zone { match { method GET POST } key {remote_host} window 1m events 100 ipv4_prefix 0 ipv6_prefix 64 } ``` -------------------------------- ### Caddyfile Rate Limiting Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Configure static and dynamic rate limits using Caddyfile syntax. This mirrors the JSON example, applying a static limit for GET requests and a dynamic limit based on the client's IP. ```caddyfile :80 rate_limit { distributed zone static_example { match { method GET } key static events 100 window 1m } zone dynamic_example { key {remote_host} events 2 window 5s } log_key } respond "I'm behind the rate limiter!" ``` -------------------------------- ### Declined Requests Metric Example Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Example Prometheus output for the `caddy_rate_limit_declined_requests_total` counter. This metric tracks requests denied due to rate limiting, with labels for zone and key. ```text caddy_rate_limit_declined_requests_total{zone="api",key=""} 1523 caddy_rate_limit_declined_requests_total{zone="api",key="192.168.1.1"} 42 caddy_rate_limit_declined_requests_total{zone="api",key="192.168.1.2"} 31 ``` -------------------------------- ### Build Caddy with Rate Limit Module Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Use xcaddy to build Caddy with the rate limit module included. Ensure you have xcaddy installed and the module path is correct. ```bash xcaddy build --with github.com/mholt/caddy-ratelimit ``` -------------------------------- ### Example Raw Metrics Output Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md This shows the typical output format for Caddy rate limit metrics when scraped by Prometheus. It includes examples for declined requests, total requests, process time histograms, and key counts. ```text # HELP caddy_rate_limit_declined_requests_total Total number of requests for which rate limit was applied (Declined with HTTP 429 status code returned). # TYPE caddy_rate_limit_declined_requests_total counter caddy_rate_limit_declined_requests_total{key="",zone="api"} 1523 caddy_rate_limit_declined_requests_total{key="192.168.1.1",zone="api"} 42 # HELP caddy_rate_limit_requests_total Total number of requests that passed through Rate Limit module (both declined & processed). # TYPE caddy_rate_limit_requests_total counter caddy_rate_limit_requests_total{key="",zone="api"} 150000 caddy_rate_limit_requests_total{key="192.168.1.1",zone="api"} 5000 # HELP caddy_rate_limit_process_time_seconds A time taken to process rate limiting for each request. # TYPE caddy_rate_limit_process_time_seconds histogram caddy_rate_limit_process_time_seconds_bucket{key="",zone="api",le="0.001"} 120000 caddy_rate_limit_process_time_seconds_bucket{key="",zone="api",le="0.005"} 149500 caddy_rate_limit_process_time_seconds_bucket{key="",zone="api",le="+Inf"} 150000 caddy_rate_limit_process_time_seconds_sum{key="",zone="api"} 42.5 caddy_rate_limit_process_time_seconds_count{key="",zone="api"} 150000 # HELP caddy_rate_limit_keys_total Total number of keys that each RL zone contains. # TYPE caddy_rate_limit_keys_total gauge caddy_rate_limit_keys_total{zone="api"} 1523 # HELP caddy_rate_limit_config Shows configuration of the rate limiter module. # TYPE caddy_rate_limit_config counter caddy_rate_limit_config{ipv4_prefix="0",ipv6_prefix="64",max_events="1000",window="1m0s",zone="api"} 1 ``` -------------------------------- ### 429 Too Many Requests Response Example Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an HTTP 429 response, including the Retry-After header. Clients should wait the indicated seconds before retrying. ```http HTTP/1.1 429 Too Many Requests Retry-After: 60 Content-Length: 0 ``` -------------------------------- ### Active Keys Gauge Example Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Example Prometheus output for the `caddy_rate_limit_keys_total` gauge. This metric indicates the current number of unique active rate limiter keys within each zone. ```text caddy_rate_limit_keys_total{zone="api"} 1523 caddy_rate_limit_keys_total{zone="anonymous"} 847 ``` -------------------------------- ### JSON Configuration for Distributed Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/distributed-ratelimiting.md Example JSON configuration for enabling distributed rate limiting. Ensure the 'handler' is set to 'rate_limit' and 'distributed' settings are provided. ```json { "handler": "rate_limit", "distributed": { "write_interval": "5s", "read_interval": "5s", "purge_age": "30m" }, "rate_limits": { /* ... */ } } ``` -------------------------------- ### Dynamic Rate Limit with Distributed RL (JSON and Caddyfile) Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Sets up a dynamic rate limit zone 'dynamic_example' using client IP addresses as keys, allowing 2 requests per IP every 5 seconds. It also enables distributed rate limiting using default settings. This example is provided in both JSON and Caddyfile formats. ```json { "handler": "rate_limit", "rate_limits": { "dynamic_example": { "key": "{http.request.remote.host}", "window": "5s", "max_events": 2 } }, "distributed": {} } ``` ```caddyfile rate_limit { zone dynamic_example { key {http.request.remote.host} window 5s events 2 } distributed } ``` -------------------------------- ### Total Requests Metric Example Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Example Prometheus output for the `caddy_rate_limit_requests_total` counter. This metric counts all requests processed by the rate limit module, including both allowed and declined requests. ```text caddy_rate_limit_requests_total{zone="api",key=""} 150000 caddy_rate_limit_requests_total{zone="api",key="192.168.1.1"} 5000 ``` -------------------------------- ### Process Time Histogram Example Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Example Prometheus output for the `caddy_rate_limit_process_time_seconds` histogram. This shows the distribution of time taken to process rate limiting decisions, including bucket counts, sum, and total count. ```text caddy_rate_limit_process_time_seconds_bucket{zone="api",key="",le="0.001"} 120000 caddy_rate_limit_process_time_seconds_bucket{zone="api",key="",le="0.005"} 149500 caddy_rate_limit_process_time_seconds_bucket{zone="api",key="",le="1.0"} 150000 caddy_rate_limit_process_time_seconds_sum{zone="api",key=""} 42.5 caddy_rate_limit_process_time_seconds_count{zone="api",key=""} 150000 ``` -------------------------------- ### Example: Per-IP Rate Limiting in JSON Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ratelimit.md Demonstrates a JSON configuration for per-IP rate limiting. It defines a 'rate_limits' block with a 'per_ip' zone that uses the client's remote host as the key, allowing 100 requests per minute. ```json { "rate_limits": { "per_ip": { "key": "{http.request.remote.host}", "window": "1m", "max_events": 100 } } } ``` -------------------------------- ### Valid JSON Configuration: Positive Window Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md A corrected JSON configuration example demonstrating a valid 'window' setting of '1m' for a rate limit zone, adhering to the requirement for a positive duration. ```json { "zone": "api", "window": "1m", "max_events": 100 } ``` -------------------------------- ### Distributed Rate Limiting (Caddyfile) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Configure cluster-wide rate limiting using Caddyfile syntax. This example uses PostgreSQL for state storage and enforces limits across all Caddy instances. ```caddyfile :80 rate_limit { distributed { write_interval 5s read_interval 5s purge_age 10m } zone api { key {remote_host} window 1m events 1000 } storage postgres "user=caddy dbname=state host=postgres.internal" } respond "Cluster-wide limited" ``` -------------------------------- ### Simple Per-IP Rate Limiting (Caddyfile) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Configure rate limiting using Caddyfile syntax for per-IP restrictions. This example allows 100 requests per minute per IP. ```caddyfile :80 rate_limit { zone api { key {remote_host} window 1m events 100 } } reverse_proxy localhost:3000 ``` -------------------------------- ### Valid JSON Configuration: IPv6Prefix Within Range Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md A corrected JSON configuration example demonstrating a valid 'ipv6_prefix' setting of 64, which is within the allowed range of 0 to 128. ```json { "ipv6_prefix": 64 } ``` -------------------------------- ### Caddyfile Configuration for Distributed Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/distributed-ratelimiting.md Example Caddyfile configuration for distributed rate limiting. This includes settings for the 'distributed' block and a sample 'zone' definition. ```caddyfile rate_limit { distributed { write_interval 5s read_interval 5s purge_age 30m } zone api { key {remote_host} window 1m events 100 } } ``` -------------------------------- ### Complex Multi-Zone Rate Limiting Setup Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Defines multiple rate limiting zones with different matching criteria, keys, windows, and event limits. Includes distributed rate limiting configuration and file-based storage. ```caddyfile :443 rate_limit { distributed { write_interval 3s read_interval 3s purge_age 5m } log_key jitter 0.1 zone static { match { method GET } key static window 1s events 1000 } zone auth_bypass { match { path /login /register } key {remote_host} window 1m events 5 } zone api { match { path /api/* } key {http.request.header.Authorization} window 1h events 50000 ipv6_prefix 64 } zone general { key {remote_host} window 1m events 100 ipv4_prefix 24 } storage file "/var/lib/caddy/rl_state" } reverse_proxy localhost:3000 ``` -------------------------------- ### Rate Limit Exceeded Log Entry (with key) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md Example log entry when `log_key` is enabled in the rate limit handler configuration. Includes zone, wait time, remote IP, and the rate limiter key. ```log 2024-01-15T10:30:45.123Z info caddy.handlers.rate_limit rate limit exceeded {"zone": "api", "wait": 60s, "remote_ip": "192.168.1.100", "key": "192.168.1.100"} ``` -------------------------------- ### Valid JSON Configuration: IPv4Prefix Within Range Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md A corrected JSON configuration example showing a valid 'ipv4_prefix' setting of 24, which falls within the allowed range of 0 to 32. ```json { "ipv4_prefix": 24 } ``` -------------------------------- ### Export Rate Limiter State for Distributed Systems Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ringbuffer-ratelimiter.md In a distributed setup, the `Count` method can be used to export the current state of a rate limiter instance. Other instances can then load this state to inform their own allowance decisions. ```go // Export this instance's rate limiter state count, oldestEvent := limiter.Count(time.Now()) // Other instances load this state from storage and account for it // in their allowance decisions ``` -------------------------------- ### Valid JSON Configuration: Non-Negative Jitter Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md A corrected JSON configuration example showing a valid 'jitter' setting of 0.2, which satisfies the requirement of being zero or a positive value. ```json { "jitter": 0.2 } ``` -------------------------------- ### Rate Limit Exceeded Log Entry (without key) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md Example log entry when `log_key` is disabled (default) in the rate limit handler configuration. Excludes the sensitive rate limiter key. ```log 2024-01-15T10:30:45.123Z info caddy.handlers.rate_limit rate limit exceeded {"zone": "api", "wait": 60s, "remote_ip": "192.168.1.100"} ``` -------------------------------- ### Caddyfile Directive Order Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Example of how to change the default order of the rate_limit directive relative to other directives like basic_auth using the 'order' global option. ```caddyfile { order rate_limit after basic_auth } ``` -------------------------------- ### Invalid JSON Configuration: IPv4Prefix Out of Range Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an invalid JSON configuration where 'ipv4_prefix' is set to 33, exceeding the maximum allowed value of 32. ```json { "ipv4_prefix": 33 } ``` -------------------------------- ### Cluster-wide Active Keys Query Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Use this PromQL query to get an approximate sum of active keys across all Caddy instances for a specific zone. ```promql # Sum of active keys across all instances (approximate) sum(caddy_rate_limit_keys_total) by (zone) ``` -------------------------------- ### Invalid JSON Configuration: Window Zero Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an invalid JSON configuration for a rate limit zone where the 'window' is set to '0s', violating the validation rule that the window must be greater than zero. ```json { "zone": "api", "window": "0s", "max_events": 100 } ``` -------------------------------- ### JSON Network Prefix Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Configure rate limiting using IPv6 prefix grouping in JSON. This example groups all IPv6 clients within the same /64 network into a single rate limit bucket. ```json { "handler": "rate_limit", "rate_limits": { "per_network": { "key": "{http.request.remote.host}", "window": "1m", "max_events": 100, "ipv6_prefix": 64 } } } ``` -------------------------------- ### Caddyfile Network Prefix Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Configure rate limiting using IPv6 prefix grouping in Caddyfile. This example groups IPv6 clients within the same /64 network into a single rate limit bucket, while IPv4 clients are limited individually. ```caddyfile rate_limit { zone per_network { key {remote_host} events 100 window 1m ipv6_prefix 64 } } ``` -------------------------------- ### Provision(ctx caddy.Context) Method Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Initializes the Handler after configuration is loaded, setting up rate limit zones, storage, metrics, and synchronization. ```APIDOC ## Provision(ctx caddy.Context) ```go func (h *Handler) Provision(ctx caddy.Context) error ``` Initializes the Handler after configuration is loaded. Sets up all rate limit zones, storage connection, metrics collection, distributed state synchronization (if enabled), and background cleanup goroutines. **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | ctx | caddy.Context | Caddy execution context providing logger, storage, metrics registry access | **Returns:** - `error`: Non-nil if initialization fails (invalid configuration, storage errors, etc.) **Side Effects:** - Provisions all RateLimit zones - Registers Prometheus metrics - Starts background goroutine for periodic rate limiter cleanup (sweep) - Starts distributed synchronization goroutine if `Distributed` is configured - Performs initial distributed state read if distributed RL is enabled **Example:** ```go handler := &Handler{ RateLimits: map[string]*RateLimit{ "api_limit": { Key: "{http.request.remote.host}", MaxEvents: 100, Window: caddy.Duration(1 * time.Minute), }, }, SweepInterval: caddy.Duration(30 * time.Second), } ctx := caddy.Context{} // obtained from Caddy if err := handler.Provision(ctx); err != nil { log.Fatal(err) } ``` **Source:** `handler.go:95` ``` -------------------------------- ### Provision Handler Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Initializes the Handler after configuration is loaded. Use this to set up rate limit zones, storage, metrics, and distributed synchronization. ```go handler := &Handler{ RateLimits: map[string]*RateLimit{ "api_limit": { Key: "{http.request.remote.host}", MaxEvents: 100, Window: caddy.Duration(1 * time.Minute), }, }, SweepInterval: caddy.Duration(30 * time.Second), } ctx := caddy.Context{} // obtained from Caddy if err := handler.Provision(ctx); err != nil { log.Fatal(err) } ``` -------------------------------- ### Get Sliding Window Duration Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ringbuffer-ratelimiter.md Retrieves the current duration of the sliding window for rate limiting. ```go func (r *ringBufferRateLimiter) Window() time.Duration ``` ```go limiter := newRingBufferRateLimiter(100, time.Minute) w := limiter.Window() // Returns 1m0s ``` -------------------------------- ### ServeHTTP Method Implementation Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Implements the HTTP middleware pattern for rate limiting. It evaluates rate limit zones, checks for exceeded limits, and enforces them. If distributed rate limiting is enabled, it consults other instances' states. Use this when integrating custom Caddy handlers or understanding the middleware flow. ```go func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error ``` -------------------------------- ### Get Maximum Events Allowed Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ringbuffer-ratelimiter.md Retrieves the current maximum number of events that can occur within the defined time window. ```go func (r *ringBufferRateLimiter) MaxEvents() int ``` ```go limiter := newRingBufferRateLimiter(100, time.Minute) max := limiter.MaxEvents() // Returns 100 ``` -------------------------------- ### Invalid JSON Configuration: Negative Jitter Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an invalid JSON configuration where 'jitter' is set to a negative value (-0.1), which is not permitted. ```json { "jitter": -0.1 } ``` -------------------------------- ### Invalid JSON Configuration: IPv6Prefix Out of Range Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an invalid JSON configuration where 'ipv6_prefix' is set to 129, exceeding the maximum allowed value of 128. ```json { "ipv6_prefix": 129 } ``` -------------------------------- ### Caddyfile Syntax for Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Illustrates the general syntax for configuring the rate_limit directive in a Caddyfile, including zone definitions and distributed settings. ```caddyfile rate_limit { zone { match { } key window events ipv4_prefix ipv6_prefix } distributed { read_interval write_interval purge_age } log_key disable_metrics storage jitter sweep_interval } ``` -------------------------------- ### Caddyfile with Environment Variable for Storage Directory Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Demonstrates using an environment variable to specify the storage directory for rate limiting. The default path is used if the environment variable is not set. ```caddyfile { storage file {$CADDY_RL_STATE_DIR:/var/lib/caddy/rl} } :80 rate_limit { zone api { key {remote_host} window 1m events 100 } } ``` -------------------------------- ### Invalid JSON Configuration: Negative MaxEvents Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md An example of an invalid JSON configuration for a rate limit zone where 'max_events' is set to a negative value (-10), which is not permitted. ```json { "zone": "api", "window": "1m", "max_events": -10 } ``` -------------------------------- ### CaddyModule Method Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Returns module metadata required by Caddy, including its identifier and factory function. ```go func (Handler) CaddyModule() caddy.ModuleInfo ``` -------------------------------- ### RLStateValue Struct Definition (Go) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/types.md Represents the state of a single rate limiter in a distributed setup. Tracks the event count and the timestamp of the oldest event within the window. ```go type rlStateValue struct { Count int OldestEvent time.Time } ``` -------------------------------- ### CaddyModule() Method Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Provides module metadata required by Caddy, including its identifier and factory function. ```APIDOC ## CaddyModule() ```go func (Handler) CaddyModule() caddy.ModuleInfo ``` Returns module metadata required by Caddy. **Returns:** - `caddy.ModuleInfo`: Module identifier `"http.handlers.rate_limit"` and factory function **Source:** `handler.go:87` ``` -------------------------------- ### Per-API-Key Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/README.md Limits API requests based on the 'X-API-Key' header, allowing 10,000 requests per hour per API key. Requests are matched if the path starts with '/api/'. ```json { "handler": "rate_limit", "rate_limits": { "api_users": { "match": [{"path": "/api/*"}], "key": "{http.request.header.X-API-Key}", "window": "1h", "max_events": 10000 } } } ``` -------------------------------- ### Per-API-Key and Per-IP Rate Limiting with Matchers (JSON) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Implement different rate limits based on request path and authentication method. Authenticated requests are limited per API key, while unauthenticated ones are limited per IP. ```json { "handler": "rate_limit", "rate_limits": { "api_authenticated": { "match": [ {"path": "/api/*"} ], "key": "{http.request.header.X-API-Key}", "window": "1h", "max_events": 10000 }, "api_anonymous": { "match": [ {"path": "/api/*"} ], "key": "{http.request.remote.host}", "window": "1m", "max_events": 100 } } } ``` -------------------------------- ### Enable Caddy Metrics (Default) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Enables Caddy's metrics endpoint, which includes rate limiting metrics by default. This configuration snippet shows the minimal JSON required. ```json { "admin": { "metrics": { "prometheus": {} } } } ``` -------------------------------- ### RateLimit Structure Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/types.md Represents a single rate limit zone with its configuration. Use this to define specific rate limiting rules, including matchers, key generation, event limits, and time windows. ```go type RateLimit struct { MatcherSetsRaw caddyhttp.RawMatcherSets `json:"match,omitempty" caddy:"namespace=http.matchers"` Key string `json:"key,omitempty"` MaxEvents int `json:"max_events,omitempty"` Window caddy.Duration `json:"window,omitempty"` IPv4Prefix int `json:"ipv4_prefix,omitempty"` IPv6Prefix int `json:"ipv6_prefix,omitempty"` } ``` -------------------------------- ### ServeHTTP Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Implements the HTTP middleware pattern for rate limiting. It evaluates rate limit zones, enforces limits, and consults distributed states if enabled. ```APIDOC ## ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) ### Description Implements the HTTP middleware pattern. Evaluates all rate limit zones in order of permissiveness (least permissive first), checking if the request matches each zone and enforcing limits. If distributed RL is enabled, consults other instances' states before deciding to allow or reject the request. ### Method ServeHTTP ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go // This is called automatically by Caddy. Direct invocation is uncommon. handler := &Handler{ /* ... */ } w := responseWriter r := httpRequest nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { w.WriteHeader(200) return nil }) err := handler.ServeHTTP(w, r, nextHandler) if err != nil { // Handle rate limit error or next handler error } ``` ### Response #### Success Response (200) Calls the next handler in the chain. #### Response Example None explicitly defined, depends on the next handler. ERROR HANDLING: - Returns `error`: Non-nil error of type `caddyhttp.HandlerError` with status 429 if any rate limit is exceeded; otherwise calls next handler and returns its error. ``` -------------------------------- ### PromQL: Rate of Declined Requests Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Calculates the rate of declined requests for a specific zone over the last 5 minutes. Use `key=""` to aggregate across all keys within a zone. ```promql rate(caddy_rate_limit_declined_requests_total{zone="api",key=""}[5m]) ``` -------------------------------- ### Drop Per-Key Metrics with Prometheus Relabeling Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Configure Prometheus scrape jobs to drop high-cardinality per-key metrics, retaining only zone-level aggregates. This example specifically targets metrics related to declined requests, total requests, and process time. ```yaml scrape_configs: - job_name: caddy metric_relabel_configs: - source_labels: [__name__] regex: "caddy_rate_limit_(declined|requests|process_time)_total.*" target_label: __tmp_keep_with_key - source_labels: [__tmp_keep_with_key, key] regex: ".*;(?!$)" action: drop ``` -------------------------------- ### Cleanup Method Implementation Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Cleans up resources associated with the rate limit handler when it is removed from the Caddy configuration. This method is called automatically by Caddy and is expected to always return nil, indicating successful cleanup. ```go func (h *Handler) Cleanup() error ``` -------------------------------- ### Create New Ring Buffer Rate Limiter Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ringbuffer-ratelimiter.md Constructs a new ring buffer rate limiter. Use this to specify the maximum number of events allowed within a given time window. ```go func newRingBufferRateLimiter(maxEvents int, window time.Duration) *ringBufferRateLimiter ``` ```go // Allow 100 requests per minute limiter := newRingBufferRateLimiter(100, time.Minute) // Allow 2 requests per 5 seconds limiter2 := newRingBufferRateLimiter(2, 5*time.Second) // Unlimited (window = 0) limiter3 := newRingBufferRateLimiter(100, 0) // No requests allowed limiter4 := newRingBufferRateLimiter(0, time.Minute) ``` -------------------------------- ### Distributed Rate Limiting with PostgreSQL Storage (JSON) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Configure cluster-wide rate limiting using PostgreSQL for state storage. This ensures rate limits are enforced consistently across all Caddy instances in a cluster. ```json { "storage": { "module": "postgres", "dsn": "user=caddy dbname=state host=postgres.internal" }, "apps": { "http": { "servers": { "main": { "listen": [":80"], "routes": [ { "handle": [ { "handler": "rate_limit", "distributed": { "write_interval": "5s", "read_interval": "5s", "purge_age": "10m" }, "rate_limits": { "api": { "key": "{http.request.remote.host}", "window": "1m", "max_events": 1000 } } } ] } ] } } } } } ``` -------------------------------- ### Constructor: newRingBufferRateLimiter Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ringbuffer-ratelimiter.md Creates a new ring buffer rate limiter instance, specifying the maximum number of events allowed within a given time window. ```APIDOC ## newRingBufferRateLimiter(maxEvents int, window time.Duration) ### Description Creates a new rate limiter allowing `maxEvents` events within a sliding window of size `window`. ### Parameters #### Path Parameters - **maxEvents** (int) - Required - Maximum number of events allowed within the window. Must be ≥ 0. If 0, no events are allowed. - **window** (time.Duration) - Required - Duration of the sliding window. Must be ≥ 0. If 0, all events are allowed (no limit). ### Returns - `*ringBufferRateLimiter`: New rate limiter instance ### Panics - If `maxEvents` < 0 - If `window` < 0 ### Example ```go // Allow 100 requests per minute limiter := newRingBufferRateLimiter(100, time.Minute) // Allow 2 requests per 5 seconds limiter2 := newRingBufferRateLimiter(2, 5*time.Second) // Unlimited (window = 0) limiter3 := newRingBufferRateLimiter(100, 0) // No requests allowed limiter4 := newRingBufferRateLimiter(0, time.Minute) ``` ``` -------------------------------- ### File Organization Structure Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/MANIFEST.md This structure shows the organization of the Caddy rate limiting module's documentation files, including the entry points, configuration references, and API details. ```text /workspace/home/output/ ├── INDEX.md ← Start here: navigation guide ├── README.md ← Quick start and overview ├── types.md ← Type definitions ├── configuration.md ← Full config reference ├── errors.md ← Error handling ├── metrics.md ← Prometheus monitoring ├── MANIFEST.md ← This file └── api-reference/ ├── handler.md ← HTTP middleware ├── ratelimit.md ← Rate limit zones ├── distributed-ratelimiting.md ← Cluster sync └── ringbuffer-ratelimiter.md ← Ring buffer internals ``` -------------------------------- ### Go Code: Window Must Be Greater Than Zero Validation Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md This Go code snippet illustrates the validation logic for the 'window' parameter in a rate limit zone, ensuring it is set to a positive duration. ```go if rl.Window <= 0 { return fmt.Errorf("window must be greater than zero") } ``` -------------------------------- ### Handler Structure Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/types.md The primary HTTP handler for rate limiting middleware. Configure rate limit zones, jitter, sweep intervals, and distributed settings here. ```go type Handler struct { RateLimits map[string]*RateLimit `json:"rate_limits,omitempty"` Jitter float64 `json:"jitter,omitempty"` SweepInterval caddy.Duration `json:"sweep_interval,omitempty"` Distributed *DistributedRateLimiting `json:"distributed,omitempty"` StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"` LogKey bool `json:"log_key,omitempty"` DisableMetrics bool `json:"disable_metrics,omitempty"` } ``` -------------------------------- ### JSON Configuration for Rate Limiting Source: https://github.com/mholt/caddy-ratelimit/blob/master/README.md Defines the structure for configuring the rate limit handler in JSON format. All fields are optional, but 'window' and 'max_events' are required for a useful zone. Supports dynamic keys and network subnet grouping. ```json { "handler": "rate_limit", "rate_limits": { "": { "match": [], "key": "", "window": "", "max_events": 0, "ipv4_prefix": 0, "ipv6_prefix": 0 } }, "jitter": 0.0, "sweep_interval": "", "log_key": false, "disable_metrics": false, "storage": {}, "distributed": { "write_interval": "", "read_interval": "", "purge_age": "" }, } ``` -------------------------------- ### PromQL: Current Active Keys per Zone Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Displays the current number of active keys being tracked by the rate limiter for each zone. This metric is useful for capacity planning. ```promql caddy_rate_limit_keys_total ``` -------------------------------- ### JSON Configuration for PostgreSQL Storage Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Configures the rate limiting module to use PostgreSQL as the storage backend for distributed rate limiting. Requires a valid connection string. ```json { "storage": { "module": "postgres", "connection_string": "user=caddy password=secret dbname=caddy_state host=db.internal port=5432" } } ``` -------------------------------- ### PromQL: Identify Heavily Limited Keys Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Identifies the top 10 keys within the 'api' zone that have been declined most frequently. Requires `key!=""` to filter out aggregated zone-level counts. ```promql topk(10, caddy_rate_limit_declined_requests_total{zone="api",key!=""}) ``` -------------------------------- ### Rate Limit Configuration Schema Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/handler.md Defines the structure for configuring rate limits in Caddy. This JSON schema specifies parameters like match rules, keys, windows, maximum events, and distributed settings. Use this to define your rate limiting policies. ```json { "handler": "rate_limit", "rate_limits": { "zone_name": { "match": [], "key": "static_or_{placeholder}", "window": "1m", "max_events": 100, "ipv4_prefix": 0, "ipv6_prefix": 0 } }, "jitter": 0.2, "sweep_interval": "1m", "log_key": false, "disable_metrics": false, "storage": {}, "distributed": { "write_interval": "5s", "read_interval": "5s", "purge_age": "0s" } } ``` -------------------------------- ### PromQL: Which Zone Is Declining Most Traffic? Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Identifies the top 5 zones experiencing the highest rate of declined requests over the last 5 minutes. ```promql topk(5, sum by (zone) (rate(caddy_rate_limit_declined_requests_total[5m]))) ``` -------------------------------- ### Caddyfile Parsing Error: Zone Window Already Specified Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md This Caddyfile snippet illustrates an error condition where a zone block has duplicate 'window' directives. ```caddyfile zone my_zone { window 1m window 2m } ``` -------------------------------- ### PromQL: Rate Limit Acceptance Rate Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Calculates the fraction of requests that are allowed by the rate limiter. A value of 0.95 means 95% are allowed and 5% are declined. ```promql 1 - (rate(caddy_rate_limit_declined_requests_total[5m]) / rate(caddy_rate_limit_requests_total[5m])) ``` -------------------------------- ### DistributedRateLimiting Structure Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/types.md Configuration for enabling and tuning distributed rate limiting across a cluster. Adjust write, read, and purge intervals to manage state synchronization. ```go type DistributedRateLimiting struct { WriteInterval caddy.Duration `json:"write_interval,omitempty"` ReadInterval caddy.Duration `json:"read_interval,omitempty"` PurgeAge caddy.Duration `json:"purge_age,omitempty"` } ``` -------------------------------- ### JSON RateLimit Zone Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Configures a specific rate limit zone, including matchers, key template, time window, maximum events, and IP prefix grouping for IPv4 and IPv6. ```json { "": { "match": [ /* Matcher[] */ ], "key": "static_or_{placeholder}", "window": "1m", "max_events": 100, "ipv4_prefix": 0, "ipv6_prefix": 0 } } ``` -------------------------------- ### PromQL: Average Processing Time Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/metrics.md Calculates the average time spent processing rate limits over a 5-minute window, in seconds. ```promql rate(caddy_rate_limit_process_time_seconds_sum[5m]) / rate(caddy_rate_limit_process_time_seconds_count[5m]) ``` -------------------------------- ### Customizing 429 Responses in Caddyfile Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md Demonstrates how to use error routes in the Caddyfile to customize the response for 429 Too Many Requests errors, including setting a JSON body with retry information. ```caddyfile rate_limit { zone api { key {remote_host} window 1m events 100 } } handle_errors { @ratelimit expression `{http.error.status_code} == 429` handle @ratelimit { header Content-Type application/json respond `{"error":"rate limit exceeded","retry_after":"{http.response.header.Retry-After}"}` 429 } } ``` -------------------------------- ### RateLimit Type Definition Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/api-reference/ratelimit.md Defines the structure of a rate limit zone, including matchers, key generation, limits, and window settings. ```go type RateLimit struct { MatcherSetsRaw caddyhttp.RawMatcherSets Key string MaxEvents int Window caddy.Duration IPv4Prefix int IPv6Prefix int } ``` -------------------------------- ### Customizing 429 Responses in JSON Configuration Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md Shows how to configure custom error routes within the JSON configuration for handling 429 Too Many Requests, providing a JSON response with retry details. ```json { "routes": [ { "handle": [ { "handler": "rate_limit", "rate_limits": { /* ... */ } } ] } ], "errors": [ { "routes": [ { "handle": [ { "handler": "static_response", "header": {"Content-Type": ["application/json"]}, "body": "{\"error\":\"rate limit exceeded\",\"retry_after\":\"{http.response.header.Retry-After}\"}" } ], "match": [ {"expression": "{http.error.status_code} == 429"} ] } ] } ] } ``` -------------------------------- ### Network Prefix Rate Limiting (Caddyfile) Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/configuration.md Apply rate limiting based on network subnet. IPv4 and IPv6 addresses within the same subnet share a rate limit bucket. ```caddyfile :80 rate_limit { zone network { key {remote_host} window 1m events 1000 ipv4_prefix 24 ipv6_prefix 64 } } respond "Limited by network subnet" ``` -------------------------------- ### Caddyfile Parsing Error: Zone Key Already Specified Source: https://github.com/mholt/caddy-ratelimit/blob/master/_autodocs/errors.md This Caddyfile snippet demonstrates an error where a zone block contains multiple 'key' directives, which is not allowed. ```caddyfile zone my_zone { key static key static2 } ```