### Integrate httprate with Chi Router Source: https://context7.com/go-chi/httprate/llms.txt Demonstrates how to apply global rate limits by IP, route-specific limits using custom context keys, and manual rate limiting for login endpoints. This example uses the httprate package to manage request flow within a standard Chi router setup. ```go package main import ( "context" "encoding/json" "log" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/httprate" ) func main() { r := chi.NewRouter() r.Use(middleware.Logger) r.Use(httprate.LimitByIP(1000, time.Minute)) r.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Welcome!")) }) r.Route("/admin", func(r chi.Router) { r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), "userID", "admin-123") next.ServeHTTP(w, r.WithContext(ctx)) }) }) r.Use(httprate.Limit( 10, time.Second, httprate.WithKeyFuncs(func(r *http.Request) (string, error) { userID, _ := r.Context().Value("userID").(string) return userID, nil }), )) r.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Admin panel")) }) }) loginLimiter := httprate.NewRateLimiter(5, time.Minute) r.Post("/login", func(w http.ResponseWriter, r *http.Request) { var payload struct { Username string `json:"username"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { http.Error(w, "Bad request", http.StatusBadRequest) return } if loginLimiter.RespondOnLimit(w, r, payload.Username) { return } w.Write([]byte("Login successful")) }) log.Println("Server starting on :3333") http.ListenAndServe(":3333", r) } ``` -------------------------------- ### Rate Limit by IP and URL Path Source: https://github.com/go-chi/httprate/blob/master/README.md This example shows how to apply rate limiting based on both the client's IP address and the requested URL path. ```APIDOC ## Rate Limit by IP and URL Path ### Description Limits requests to 10 per 10 seconds, considering both the client's IP and the specific endpoint (URL path) being accessed. ### Method Uses Go's `net/http` middleware pattern with custom key functions. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **keyFuncs** ([]httprate.KeyFunc) - Required - Functions to generate keys for rate limiting (e.g., `httprate.KeyByIP`, `httprate.KeyByEndpoint`). ### Request Example ```go r.Use(httprate.Limit( 10, // requests 10*time.Second, // per duration httprate.WithKeyFuncs(httprate.KeyByIP, httprate.KeyByEndpoint), )) ``` ### Response - **429 Too Many Requests**: Returned when the rate limit is exceeded for a specific IP/endpoint combination. ### Response Example ``` HTTP 429 Too Many Requests ``` ``` -------------------------------- ### Go: Customize Request Grouping with Key Functions (WithKeyFuncs) Source: https://context7.com/go-chi/httprate/llms.txt Illustrates how to use httprate.WithKeyFuncs to define custom logic for grouping requests for rate limiting. This example combines IP address, endpoint, and an API token to create unique rate limiting contexts. ```go package main import ( "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Combine multiple key functions - rate limit by IP AND endpoint rateLimiter := httprate.Limit( 10, time.Second, httprate.WithKeyFuncs( httprate.KeyByIP, httprate.KeyByEndpoint, // Custom key function for API token func(r *http.Request) (string, error) { return r.Header.Get("X-API-Token"), nil }, ), ) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Rate limited by IP + endpoint + token")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Rate Limit Login Attempts by Username Source: https://github.com/go-chi/httprate/blob/master/README.md This example shows how to rate limit login attempts specifically for each username to prevent brute-force attacks. ```APIDOC ## Rate Limit Login Attempts by Username ### Description Limits login attempts to 5 per minute for each unique username. This uses a dedicated `RateLimiter` instance. ### Method Uses a `httprate.RateLimiter` instance within a request handler. ### Endpoint Applies to the `/login` POST endpoint. ### Parameters - **requests** (int) - Required - The maximum number of login attempts allowed per username. - **duration** (time.Duration) - Required - The time window for the rate limit. - **payload.Username** (string) - Required - Used as the key for rate limiting. ### Request Example ```go // Initialize the rate limiter loginRateLimiter := httprate.NewRateLimiter(5, time.Minute) r.Post("/login", func(w http.ResponseWriter, r *http.Request) { var payload struct { Username string `json:"username"` Password string `json:"password"` } err := json.NewDecoder(r.Body).Decode(&payload) if err != nil || payload.Username == "" || payload.Password == "" { w.WriteHeader(400) return } // Check rate limit before proceeding if loginRateLimiter.RespondOnLimit(w, r, payload.Username) { return } w.Write([]byte("login at 5 req/min\n")) }) ``` ### Response - **429 Too Many Requests**: Returned when a username exceeds the login attempt limit. - **400 Bad Request**: Returned for invalid login payload. ### Response Example ``` HTTP 429 Too Many Requests ``` ``` -------------------------------- ### Go: Get Current Rate Limit Status (Status) Source: https://context7.com/go-chi/httprate/llms.txt Shows how to use httprate.Status to retrieve the current rate limit status for a given key without affecting the rate limit count. This is useful for displaying remaining quota information to users. ```go package main import ( "fmt" "net/http" "time" "github.com/go-chi/httprate" ) func main() { limiter := httprate.NewRateLimiter(100, time.Minute) http.HandleFunc("/api/quota", func(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("X-User-ID") // Get current rate limit status without incrementing ok, currentRate, err := limiter.Status(userID) if err != nil { http.Error(w, "Error checking status", http.StatusInternalServerError) return } remaining := 100 - int(currentRate) if remaining < 0 { remaining = 0 } fmt.Fprintf(w, "Rate limit OK: %v, Current rate: %.2f, Remaining: %d\n", ok, currentRate, remaining) }) http.ListenAndServe(":8080", nil) } ``` -------------------------------- ### Implement Custom Rate Limit Backends with LimitCounter Interface Source: https://context7.com/go-chi/httprate/llms.txt Defines the LimitCounter interface, allowing developers to implement custom rate limit backends, such as Redis for distributed rate limiting. The example shows a basic in-memory implementation using a map. ```go package main import ( "net/http" sync "sync" time "time" "github.com/go-chi/httprate" ) // CustomCounter implements httprate.LimitCounter for custom storage type CustomCounter struct { mu sync.Mutex counts map[string]int window time.Duration } func (c *CustomCounter) Config(requestLimit int, windowLength time.Duration) { c.window = windowLength } func (c *CustomCounter) Increment(key string, currentWindow time.Time) error { return c.IncrementBy(key, currentWindow, 1) } func (c *CustomCounter) IncrementBy(key string, currentWindow time.Time, amount int) error { c.mu.Lock() defer c.mu.Unlock() fullKey := key + currentWindow.String() c.counts[fullKey] += amount return nil } func (c *CustomCounter) Get(key string, currentWindow, previousWindow time.Time) (int, int, error) { c.mu.Lock() defer c.mu.Unlock() curr := c.counts[key+currentWindow.String()] prev := c.counts[key+previousWindow.String()] return curr, prev, nil } func main() { counter := &CustomCounter{counts: make(map[string]int)} mux := http.NewServeMux() rateLimiter := httprate.Limit( 100, time.Minute, httprate.WithKeyFuncs(httprate.KeyByIP), httprate.WithLimitCounter(counter), ) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Using custom counter backend")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Go: Customize Error Handling (WithErrorHandler) Source: https://context7.com/go-chi/httprate/llms.txt Explains how to use httprate.WithErrorHandler to manage errors that occur during the rate limiting process, such as issues with key functions or the limit counter. This example logs the error and returns a standardized internal server error response. ```go package main import ( "encoding/json" "log" "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() rateLimiter := httprate.Limit( 100, time.Minute, httprate.WithKeyFuncs(httprate.KeyByIP), httprate.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) { log.Printf("Rate limiter error: %v", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "error": "internal_error", "message": "An error occurred processing your request", }) }), ) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Custom Error Handling for Rate Limiter Errors Source: https://github.com/go-chi/httprate/blob/master/README.md This example demonstrates how to handle errors that might occur during the rate limiting process, such as issues with custom key functions or backends. ```APIDOC ## Custom Error Handling for Rate Limiter Errors ### Description Provides a custom error handler function to manage and format errors that occur within the rate limiting middleware, such as errors from custom key functions or backends. ### Method Uses Go's `net/http` middleware pattern with `httprate.WithErrorHandler`. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **errorHandler** (func(http.ResponseWriter, *http.Request, error)) - Required - A function to handle errors. - **limitCounter** (httprate.LimitCounter) - Optional - A custom backend for storing rate limit counts. ### Request Example ```go r.Use(httprate.Limit( 10, time.Minute, httprate.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) { http.Error(w, fmt.Sprintf(`{"error": %q}`, err), http.StatusPreconditionRequired) }), httprate.WithLimitCounter(customBackend), )) ``` ### Response - **412 Precondition Failed**: Returned with a formatted error message when an error occurs during rate limiting. ### Response Example ```json { "error": "" } ``` ``` -------------------------------- ### Omit Response Headers Source: https://github.com/go-chi/httprate/blob/master/README.md This example shows how to disable the addition of any rate limit-related response headers. ```APIDOC ## Omit Response Headers ### Description Disables the addition of any rate limit status headers to the HTTP response. ### Method Uses Go's `net/http` middleware pattern with `httprate.WithResponseHeaders`. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **responseHeaders** (httprate.ResponseHeaders) - Required - An empty struct to indicate no headers should be added. ### Request Example ```go r.Use(httprate.Limit( 1000, time.Minute, httprate.WithResponseHeaders(httprate.ResponseHeaders{}), )) ``` ### Response - **No Rate Limit Headers**: No specific rate limit headers are included in the response. ### Response Example ``` (No rate limit headers) ``` ``` -------------------------------- ### Implement Basic IP-based Rate Limiting Source: https://github.com/go-chi/httprate/blob/master/README.md Demonstrates how to integrate the httprate middleware into a chi router to limit requests by IP address. ```go r.Use(httprate.LimitByIP(100, time.Minute)) ``` -------------------------------- ### Configure Custom Responses and Headers Source: https://github.com/go-chi/httprate/blob/master/README.md Explains how to override default 429 responses, handle errors, and customize rate-limit response headers. ```go r.Use(httprate.Limit(10, time.Minute, httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) { http.Error(w, `{"error": "Rate-limited. Please, slow down."}`, http.StatusTooManyRequests) }))) r.Use(httprate.Limit(1000, time.Minute, httprate.WithResponseHeaders(httprate.ResponseHeaders{ Limit: "X-RateLimit-Limit", Remaining: "X-RateLimit-Remaining", Reset: "X-RateLimit-Reset", RetryAfter: "Retry-After", }))) ``` -------------------------------- ### Rate Limit by Custom Keys Source: https://github.com/go-chi/httprate/blob/master/README.md Shows how to use custom key functions to limit requests based on specific criteria like URL paths or request headers. ```go r.Use(httprate.Limit(10, 10*time.Second, httprate.WithKeyFuncs(httprate.KeyByIP, httprate.KeyByEndpoint))) r.Use(httprate.Limit(100, time.Minute, httprate.WithKeyFuncs(func(r *http.Request) (string, error) { return r.Header.Get("X-Access-Token"), nil }))) ``` -------------------------------- ### Basic Rate Limiting by IP Source: https://github.com/go-chi/httprate/blob/master/README.md This snippet demonstrates how to set up a basic rate limiter that restricts requests to 100 per minute, keyed by the client's IP address. ```APIDOC ## Basic Rate Limiting by IP ### Description Applies a rate limit of 100 requests per minute, using the client's IP address as the key. ### Method Uses Go's `net/http` middleware pattern. ### Endpoint Applies globally to all routes handled by the router. ### Parameters N/A (Middleware applies to all requests) ### Request Example ```go r.Use(httprate.LimitByIP(100, time.Minute)) ``` ### Response - **429 Too Many Requests**: Returned when the rate limit is exceeded. ### Response Example ``` HTTP 429 Too Many Requests ``` ``` -------------------------------- ### Go: Check Rate Limit Status Without Response (OnLimit) Source: https://context7.com/go-chi/httprate/llms.txt Demonstrates how to use httprate.OnLimit to check if a request exceeds the rate limit without automatically sending a response. This allows for custom handling of rate-limited requests, such as returning a JSON error message. ```go package main import ( "encoding/json" "net/http" "time" "github.com/go-chi/httprate" ) func main() { limiter := httprate.NewRateLimiter(10, time.Minute) http.HandleFunc("/api/action", func(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("X-User-ID") // OnLimit returns true if rate limited, but doesn't send response if limiter.OnLimit(w, r, userID) { // Custom rate limit response w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusTooManyRequests) json.NewEncoder(w).Encode(map[string]string{ "error": "rate_limited", "message": "Please slow down and try again later", }) return } w.Write([]byte("Action completed")) }) http.ListenAndServe(":8080", nil) } ``` -------------------------------- ### Configure Custom Rate Limiter Source: https://context7.com/go-chi/httprate/llms.txt Creates a flexible rate limiter using custom key functions. This allows for granular control over which requests are counted towards the limit. ```go package main import ( "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Limit all requests to 100 per minute with custom key functions rateLimiter := httprate.Limit( 100, // requests time.Minute, // per duration httprate.WithKeyFuncs(httprate.KeyByIP, httprate.KeyByEndpoint), ) mux.Handle("/api/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Go: Customize Rate Limited Response Handler (WithLimitHandler) Source: https://context7.com/go-chi/httprate/llms.txt Demonstrates how to use httprate.WithLimitHandler to provide a custom response when a request is rate limited. This allows for tailored JSON error messages, status codes, and retry information. ```go package main import ( "encoding/json" "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() rateLimiter := httprate.Limit( 10, time.Minute, httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusTooManyRequests) json.NewEncoder(w).Encode(map[string]interface{}{ "error": "rate_limit_exceeded", "message": "Too many requests. Please slow down.", "retry_after": 60, }) }), ) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Create In-Memory Counter with NewLocalLimitCounter Source: https://context7.com/go-chi/httprate/llms.txt Provides a factory function to create an in-memory limit counter. This counter includes automatic window eviction and serves as the default backend for httprate when no custom counter is specified. It's suitable for single-instance applications. ```go package main import ( "fmt" time "time" "github.com/go-chi/httprate" ) func main() { // Create a local counter with 1-minute windows counter := httprate.NewLocalLimitCounter(time.Minute) // Configure (optional - done automatically when used with NewRateLimiter) counter.Config(100, time.Minute) currentWindow := time.Now().UTC().Truncate(time.Minute) // Increment counter for a key counter.Increment("user:123", currentWindow) counter.IncrementBy("user:123", currentWindow, 5) // Get current and previous window counts previousWindow := currentWindow.Add(-time.Minute) curr, prev, _ := counter.Get("user:123", currentWindow, previousWindow) fmt.Printf("Current window: %d, Previous window: %d\n", curr, prev) // Output: Current window: 6, Previous window: 0 } ``` -------------------------------- ### Dynamically Adjust Limits with WithRequestLimit Source: https://context7.com/go-chi/httprate/llms.txt Provides a way to dynamically adjust the rate limit for specific requests based on certain conditions. This is useful for implementing tiered access, such as granting higher limits to premium users. ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() rateLimiter := httprate.LimitByIP(100, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Premium users get higher limits if r.Header.Get("X-Premium-User") == "true" { ctx := httprate.WithRequestLimit(r.Context(), 1000) r = r.WithContext(ctx) } w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Implement IP-based Rate Limiting Source: https://context7.com/go-chi/httprate/llms.txt Uses the LimitByIP helper to restrict requests based on the client's IP address. This is the standard approach for preventing abuse from individual users. ```go package main import ( "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Limit to 100 requests per minute per IP address rateLimiter := httprate.LimitByIP(100, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Implement Real-IP Rate Limiting Source: https://context7.com/go-chi/httprate/llms.txt Uses LimitByRealIP to correctly identify client IPs when the server is behind a reverse proxy like Nginx or Cloudflare. It checks headers like X-Forwarded-For to determine the true source. ```go package main import ( "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // For applications behind reverse proxies (nginx, cloudflare, etc.) // Uses True-Client-IP > X-Real-IP > X-Forwarded-For > RemoteAddr rateLimiter := httprate.LimitByRealIP(50, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Rate limited by real IP")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### httprate.Limit - General Rate Limiter Middleware Source: https://context7.com/go-chi/httprate/llms.txt Creates a general rate limiter middleware with configurable options for request limiting within a time window. It supports custom key functions to define what constitutes a unique rate-limiting entity (e.g., IP address, endpoint). ```APIDOC ## httprate.Limit - General Rate Limiter Middleware ### Description Creates a rate limiter middleware with configurable options for request limiting within a time window. Supports custom key functions for flexible rate limiting strategies. ### Method N/A (This is a Go function that returns middleware) ### Endpoint N/A (Applied to HTTP handlers) ### Parameters #### Function Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window duration for the rate limit. - **options** (...httprate.Option) - Optional - Configuration options like key functions. ### Request Example ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Limit all requests to 100 per minute with custom key functions rateLimiter := httprate.Limit( 100, // requests time.Minute, // per duration httprate.WithKeyFuncs(httprate.KeyByIP, httprate.KeyByEndpoint), ) mux.Handle("/api/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` ### Response #### Success Response (200) - **N/A** (The middleware modifies the request or response, actual handler logic determines the response) #### Response Example (Depends on the wrapped handler. If rate limit is exceeded, a 429 Too Many Requests response is typically returned.) ``` -------------------------------- ### Customize Response Headers with WithResponseHeaders Source: https://context7.com/go-chi/httprate/llms.txt Allows customization or complete disabling of rate limit response headers. You can specify custom names for limit, remaining, reset, and retry-after headers, or omit them entirely by providing an empty struct. ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Custom header names rateLimiter := httprate.Limit( 1000, time.Minute, httprate.WithResponseHeaders(httprate.ResponseHeaders{ Limit: "X-RateLimit-Limit", Remaining: "X-RateLimit-Remaining", Reset: "X-RateLimit-Reset", RetryAfter: "Retry-After", Increment: "", // Omit this header }), ) mux.Handle("/api/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }))) // Disable all rate limit headers silentLimiter := httprate.Limit( 100, time.Minute, httprate.WithResponseHeaders(httprate.ResponseHeaders{}), ) mux.Handle("/silent/", silentLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK without headers")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Implement Global Rate Limiting Source: https://context7.com/go-chi/httprate/llms.txt Applies a global rate limit to all incoming requests regardless of the source. This is useful for protecting shared resources or API endpoints from overall traffic spikes. ```go package main import ( "net/http" "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Global limit of 1000 requests per minute across all clients rateLimiter := httprate.LimitAll(1000, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Globally rate limited")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### httprate.NewRateLimiter - Programmatic Rate Limiter Source: https://context7.com/go-chi/httprate/llms.txt Creates a RateLimiter instance that can be used programmatically within handlers. This is useful for implementing custom rate-limiting logic, such as limiting based on request payload content (e.g., username in a login request). ```APIDOC ## httprate.NewRateLimiter - Programmatic Rate Limiter ### Description Creates a RateLimiter instance for programmatic rate limit checking. This allows for more granular control, such as limiting based on request payload fields or custom logic within a handler. ### Method N/A (This is a Go function that returns a RateLimiter object) ### Endpoint N/A (Used within HTTP handlers) ### Parameters #### Function Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window duration. ### Request Example ```go package main import ( "encoding/json" "net/http" time "time" "github.com/go-chi/httprate" ) func main() { // Create rate limiter for login endpoint: 5 attempts per minute per username loginRateLimiter := httprate.NewRateLimiter(5, time.Minute) http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { var payload struct { Username string `json:"username"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { http.Error(w, "Invalid request", http.StatusBadRequest) return } // Rate limit by username - returns true if limit exceeded if loginRateLimiter.RespondOnLimit(w, r, payload.Username) { return // 429 Too Many Requests already sent } // Process login... w.Write([]byte("Login successful")) }) http.ListenAndServe(":8080", nil) } ``` ### Response #### Success Response (200) - **N/A** (The handler logic determines the response. The `RespondOnLimit` method handles the 429 response if the limit is exceeded.) #### Response Example (If rate limit is exceeded, a 429 Too Many Requests response is returned by `RespondOnLimit`.) ``` -------------------------------- ### Programmatic Rate Limiting Source: https://context7.com/go-chi/httprate/llms.txt Uses NewRateLimiter for manual control over rate limiting. This is ideal for logic that depends on request payloads, such as limiting login attempts by username. ```go package main import ( "encoding/json" "net/http" "time" "github.com/go-chi/httprate" ) func main() { // Create rate limiter for login endpoint: 5 attempts per minute per username loginRateLimiter := httprate.NewRateLimiter(5, time.Minute) http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { var payload struct { Username string `json:"username"` Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { http.Error(w, "Invalid request", http.StatusBadRequest) return } // Rate limit by username - returns true if limit exceeded if loginRateLimiter.RespondOnLimit(w, r, payload.Username) { return // 429 Too Many Requests already sent } // Process login... w.Write([]byte("Login successful")) }) http.ListenAndServe(":8080", nil) } ``` -------------------------------- ### httprate.LimitAll - Global Rate Limiter Source: https://context7.com/go-chi/httprate/llms.txt Rate limits all requests globally, irrespective of the source IP or other identifiers. This is useful for protecting an entire service or specific endpoints with a single, shared limit. ```APIDOC ## httprate.LimitAll - Global Rate Limiter ### Description Rate limits all requests globally regardless of source, useful for protecting endpoints with a single shared limit. All requests share the same counter. ### Method N/A (This is a Go function that returns middleware) ### Endpoint N/A (Applied to HTTP handlers) ### Parameters #### Function Parameters - **requests** (int) - Required - The maximum number of requests allowed globally. - **duration** (time.Duration) - Required - The time window duration. ### Request Example ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Global limit of 1000 requests per minute across all clients rateLimiter := httprate.LimitAll(1000, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Globally rate limited")) }))) http.ListenAndServe(":8080", mux) } ``` ### Response #### Success Response (200) - **N/A** (The middleware modifies the request or response, actual handler logic determines the response) #### Response Example (If rate limit is exceeded, a 429 Too Many Requests response is returned.) ``` -------------------------------- ### Rate Limit by Custom Header Source: https://github.com/go-chi/httprate/blob/master/README.md This snippet demonstrates how to rate limit requests based on a custom header value, such as an API key. ```APIDOC ## Rate Limit by Custom Header ### Description Applies a rate limit of 100 requests per minute, using the value of the `X-Access-Token` header as the key. ### Method Uses Go's `net/http` middleware pattern with a custom key function. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **keyFuncs** ([]httprate.KeyFunc) - Required - A custom function to extract the key from the request header. ### Request Example ```go r.Use(httprate.Limit( 100, time.Minute, httprate.WithKeyFuncs(func(r *http.Request) (string, error) { return r.Header.Get("X-Access-Token"), nil }), )) ``` ### Response - **429 Too Many Requests**: Returned when the rate limit is exceeded for a specific token. ### Response Example ``` HTTP 429 Too Many Requests ``` ``` -------------------------------- ### Count Requests as Multiple Increments with WithIncrement Source: https://context7.com/go-chi/httprate/llms.txt Enables counting a single request as multiple increments against the rate limit. This is useful for operations that are more resource-intensive than a standard request, allowing them to consume more of the rate limit quota. ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() rateLimiter := httprate.LimitByIP(100, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Expensive operations count as multiple requests if r.URL.Query().Get("expensive") == "true" { ctx := httprate.WithIncrement(r.Context(), 10) r = r.WithContext(ctx) } w.Write([]byte("OK")) }))) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Custom Response Headers for Rate Limiting Source: https://github.com/go-chi/httprate/blob/master/README.md This snippet shows how to add custom HTTP headers to responses to provide information about the rate limit status. ```APIDOC ## Custom Response Headers for Rate Limiting ### Description Adds custom headers to the HTTP response to indicate the rate limit status, including the limit, remaining requests, and reset time. ### Method Uses Go's `net/http` middleware pattern with `httprate.WithResponseHeaders`. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **responseHeaders** (httprate.ResponseHeaders) - Required - Configuration for custom response headers. - **Limit** (string) - Header name for the total limit. - **Remaining** (string) - Header name for remaining requests. - **Reset** (string) - Header name for the reset time. - **RetryAfter** (string) - Header name for when to retry. - **Increment** (string) - Header name for increment (can be omitted by setting to ""). ### Request Example ```go r.Use(httprate.Limit( 1000, time.Minute, httprate.WithResponseHeaders(httprate.ResponseHeaders{ Limit: "X-RateLimit-Limit", Remaining: "X-RateLimit-Remaining", Reset: "X-RateLimit-Reset", RetryAfter: "Retry-After", Increment: "", // omit }), )) ``` ### Response - **Custom Headers**: Includes headers like `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and `Retry-After`. ### Response Example ``` X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1678886400 Retry-After: 60 ``` ``` -------------------------------- ### httprate.LimitByRealIP - Rate Limiter by Real Client IP Source: https://context7.com/go-chi/httprate/llms.txt Rate limits requests by the client's real IP address, considering headers like True-Client-IP, X-Real-IP, and X-Forwarded-For, which is crucial for applications behind proxies or load balancers. ```APIDOC ## httprate.LimitByRealIP - Rate Limiter by Real Client IP ### Description Rate limits by real client IP, checking True-Client-IP, X-Real-IP, and X-Forwarded-For headers for proxy/load balancer scenarios. It falls back to RemoteAddr if headers are not present. ### Method N/A (This is a Go function that returns middleware) ### Endpoint N/A (Applied to HTTP handlers) ### Parameters #### Function Parameters - **requests** (int) - Required - The maximum number of requests allowed per real IP. - **duration** (time.Duration) - Required - The time window duration. ### Request Example ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // For applications behind reverse proxies (nginx, cloudflare, etc.) // Uses True-Client-IP > X-Real-IP > X-Forwarded-For > RemoteAddr rateLimiter := httprate.LimitByRealIP(50, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Rate limited by real IP")) }))) http.ListenAndServe(":8080", mux) } ``` ### Response #### Success Response (200) - **N/A** (The middleware modifies the request or response, actual handler logic determines the response) #### Response Example (If rate limit is exceeded, a 429 Too Many Requests response is returned.) ``` -------------------------------- ### Custom Response for Rate-Limited Requests Source: https://github.com/go-chi/httprate/blob/master/README.md This snippet shows how to customize the HTTP response when a rate limit is exceeded. ```APIDOC ## Custom Response for Rate-Limited Requests ### Description Configures the rate limiter to return a custom JSON error message and status code when the rate limit is exceeded. ### Method Uses Go's `net/http` middleware pattern with `httprate.WithLimitHandler`. ### Endpoint Applies globally to all routes handled by the router. ### Parameters - **requests** (int) - Required - The maximum number of requests allowed. - **duration** (time.Duration) - Required - The time window for the rate limit. - **limitHandler** (func(http.ResponseWriter, *http.Request)) - Required - A function to handle the rate-limited response. ### Request Example ```go r.Use(httprate.Limit( 10, time.Minute, httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) { http.Error(w, `{"error": "Rate-limited. Please, slow down."`, http.StatusTooManyRequests) }), )) ``` ### Response - **429 Too Many Requests**: Returned with a custom JSON body when the rate limit is exceeded. ### Response Example ```json { "error": "Rate-limited. Please, slow down." } ``` ``` -------------------------------- ### httprate.LimitByIP - Rate Limiter by IP Address Source: https://context7.com/go-chi/httprate/llms.txt A convenience middleware that rate limits requests based on the client's IP address. It's a common use case for protecting against brute-force attacks. ```APIDOC ## httprate.LimitByIP - Rate Limiter by IP Address ### Description Convenience middleware that rate limits requests by client IP address. It automatically uses the client's remote address as the key for rate limiting. ### Method N/A (This is a Go function that returns middleware) ### Endpoint N/A (Applied to HTTP handlers) ### Parameters #### Function Parameters - **requests** (int) - Required - The maximum number of requests allowed per IP. - **duration** (time.Duration) - Required - The time window duration. ### Request Example ```go package main import ( "net/http" time "time" "github.com/go-chi/httprate" ) func main() { mux := http.NewServeMux() // Limit to 100 requests per minute per IP address rateLimiter := httprate.LimitByIP(100, time.Minute) mux.Handle("/", rateLimiter(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }))) http.ListenAndServe(":8080", mux) } ``` ### Response #### Success Response (200) - **N/A** (The middleware modifies the request or response, actual handler logic determines the response) #### Response Example ``` # Response headers include: X-RateLimit-Limit: 100 X-RateLimit-Remaining: 99 X-RateLimit-Reset: 1699999999 ``` (If rate limit is exceeded, a 429 Too Many Requests response is returned.) ``` -------------------------------- ### Manual Rate Limiting for Payloads Source: https://github.com/go-chi/httprate/blob/master/README.md Utilizes the RateLimiter object to manually enforce limits on specific endpoints based on request body content. ```go loginRateLimiter := httprate.NewRateLimiter(5, time.Minute) r.Post("/login", func(w http.ResponseWriter, r *http.Request) { // ... decoding logic ... if loginRateLimiter.RespondOnLimit(w, r, payload.Username) { return } w.Write([]byte("login at 5 req/min\n")) }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.