### Install Limiter Go Package Source: https://github.com/ulule/limiter/blob/master/README.md This command installs the Limiter package version v3.11.2 using Go Modules. Ensure you have Go Modules enabled in your project. ```bash go get github.com/ulule/limiter/v3@v3.11.2 ``` -------------------------------- ### Bash: Example of X-Forwarded-For request to load balancer Source: https://github.com/ulule/limiter/blob/master/README.md This bash snippet demonstrates a curl request to a load balancer with the 'X-Forwarded-For' header. It illustrates how the header can be appended with the actual client IP by the server behind the load balancer, highlighting its unreliability for direct IP sourcing. ```bash curl -X POST https://example.com/login -H "X-Forwarded-For: 1.2.3.4, 11.22.33.44" ``` -------------------------------- ### Manual Rate Limit Checking with Memory Store Source: https://context7.com/ulule/limiter/llms.txt Enables manual checking and incrementing of rate limits for custom logic without relying on middleware. This example uses an in-memory store and demonstrates how to retrieve limit details like remaining requests and reset time. ```go package main import ( "context" "fmt" "time" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { // Setup limiter rate, _ := limiter.NewRateFromFormatted("5-M") store := memory.NewStore() limiterInstance := limiter.New(store, rate) ctx := context.Background() userID := "user_12345" // Get current limit (increments counter) limitContext, err := limiterInstance.Get(ctx, userID) if err != nil { panic(err) } fmt.Printf("Limit: %d\n", limitContext.Limit) // 5 fmt.Printf("Remaining: %d\n", limitContext.Remaining) // 4 fmt.Printf("Reset: %d\n", limitContext.Reset) // Unix timestamp fmt.Printf("Reached: %v\n", limitContext.Reached) // false if limitContext.Reached { fmt.Println("Rate limit exceeded!") resetTime := time.Unix(limitContext.Reset, 0) fmt.Printf("Try again after: %s\n", resetTime) } else { fmt.Println("Request allowed") } } ``` -------------------------------- ### FastHTTP Middleware Integration for Rate Limiting Source: https://context7.com/ulule/limiter/llms.txt Integrates rate limiting into FastHTTP applications using the Limiter library. It requires the `fasthttp` and `limiter` packages, along with the specific `fasthttp` middleware driver. This setup allows for high-performance rate limiting. ```go package main import ( "github.com/valyala/fasthttp" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" fasthttpmiddleware "github.com/ulule/limiter/v3/drivers/middleware/fasthttp" ) func main() { // Create rate limiter: 50 requests per second rate, err := limiter.NewRateFromFormatted("50-S") if err != nil { panic(err) } store := memory.NewStore() limiterInstance := limiter.New(store, rate) // Create FastHTTP middleware middleware := fasthttpmiddleware.NewMiddleware(limiterInstance) // Define handler handler := func(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(200) ctx.SetBodyString("Hello, World!") } // Wrap handler with middleware rateLimitedHandler := middleware.Handle(handler) // Start server fasthttp.ListenAndServe(":8080", rateLimitedHandler) } ``` -------------------------------- ### Configure Custom Client IP Headers for CDN/Cloud Source: https://context7.com/ulule/limiter/llms.txt This snippet demonstrates how to configure custom headers for client IP detection when using Content Delivery Networks (CDNs) or cloud providers. It shows examples for Cloudflare, Fastly, and Azure, allowing the limiter to correctly identify client IPs behind these services. Dependencies include the limiter library and its store/middleware drivers. ```go package main import ( "net/http" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { rate, _ := limiter.NewRateFromFormatted("50-M") store := memory.NewStore() // For Cloudflare limiterCF := limiter.New( store, rate, limiter.WithClientIPHeader("CF-Connecting-IP"), ) // For Fastly limiterFastly := limiter.New( store, rate, limiter.WithClientIPHeader("Fastly-Client-IP"), ) // For Azure limiterAzure := limiter.New( store, rate, limiter.WithClientIPHeader("X-Azure-ClientIP"), ) // Use in middleware middleware := stdlib.NewMiddleware(limiterCF) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Rate limited with CDN support")) }) http.ListenAndServe(":8080", middleware.Handler(handler)) } ``` -------------------------------- ### Reset Rate Limits Programmatically in Go Source: https://context7.com/ulule/limiter/llms.txt Enables resetting rate limit counters for specific clients or keys. This is useful for situations where a user's limits should be refreshed, such as after an administrative action or at the start of a new period. It requires a context, the client key, and an initialized limiter instance. ```go package main import ( "context" "fmt" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { rate, _ := limiter.NewRateFromFormatted("5-M") store := memory.NewStore() limiterInstance := limiter.New(store, rate) ctx := context.Background() userID := "user_12345" // Make several requests for i := 0; i < 4; i++ { limiterInstance.Get(ctx, userID) } // Check status beforeReset, _ := limiterInstance.Peek(ctx, userID) fmt.Printf("Before reset - Remaining: %d\n", beforeReset.Remaining) // 1 // Reset the limit for this user afterReset, err := limiterInstance.Reset(ctx, userID) if err != nil { panic(err) } fmt.Printf("After reset - Remaining: %d\n", afterReset.Remaining) // 5 fmt.Printf("Reached: %v\n", afterReset.Reached) // false } ``` -------------------------------- ### Enable Trust for Forward Headers (X-Forwarded-For, X-Real-IP) Source: https://context7.com/ulule/limiter/llms.txt This example shows how to configure the limiter to trust forward headers like X-Forwarded-For and X-Real-IP. This is crucial when your application is behind a reverse proxy, as it allows the limiter to determine the original client IP address. A security warning is included, emphasizing the need to ensure these headers are reliably set by the proxy. Dependencies include net/http, limiter, and its store/middleware drivers. ```go package main import ( "net/http" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { rate, _ := limiter.NewRateFromFormatted("60-M") store := memory.NewStore() // Enable trust for X-Forwarded-For and X-Real-IP headers // SECURITY WARNING: Only enable if your reverse proxy is configured // to always overwrite these headers with trustworthy values limiterInstance := limiter.New( store, rate, limiter.WithTrustForwardHeader(true), ) // The limiter will now check headers in this order: // 1. X-Forwarded-For (first IP in the list) // 2. X-Real-IP // 3. RemoteAddr (fallback) middleware := stdlib.NewMiddleware(limiterInstance) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Rate limiting with proxy support")) }) http.ListenAndServe(":8080", middleware.Handler(handler)) } ``` -------------------------------- ### Create Limiter Instance (Go) Source: https://context7.com/ulule/limiter/llms.txt Demonstrates how to create a rate limiter instance with a specified rate and storage backend (in-memory). It also shows how to configure options like IP masking and custom client IP headers for advanced scenarios. Dependencies include the 'limiter/v3' package and specific store drivers like 'memory'. ```go package main import ( "net" "time" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { // Define rate: 100 requests per hour rate := limiter.Rate{ Period: 1 * time.Hour, Limit: 100, } // Create in-memory store store := memory.NewStore() // Create limiter instance instance := limiter.New(store, rate) // Alternative: create with options for IP masking and header trust mask := net.CIDRMask(24, 32) // /24 subnet for IPv4 instanceWithOpts := limiter.New( store, rate, limiter.WithIPv4Mask(mask), limiter.WithClientIPHeader("CF-Connecting-IP"), ) } ``` -------------------------------- ### Create Standard HTTP Limiter Middleware Source: https://github.com/ulule/limiter/blob/master/README.md Initializes the standard Go HTTP middleware for the Limiter library. This middleware can be directly integrated into your net/http server handlers to apply rate limiting. ```go import "github.com/ulule/limiter/v3/drivers/middleware/stdlib" middleware := stdlib.NewMiddleware(instance) ``` -------------------------------- ### Gin Framework Middleware Integration (Go) Source: https://context7.com/ulule/limiter/llms.txt Provides middleware integration for the Gin web framework. It shows how to create a rate limiter and then use the `ginmiddleware` to protect routes. The middleware can be applied globally to all routes or selectively to specific endpoints. Requires 'gin', 'limiter/v3', 'limiter/v3/drivers/store/memory', and 'limiter/v3/drivers/middleware/gin'. ```go package main import ( "github.com/gin-gonic/gin" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ginmiddleware "github.com/ulule/limiter/v3/drivers/middleware/gin" ) func main() { // Create rate limiter: 100 requests per hour rate, err := limiter.NewRateFromFormatted("100-H") if err != nil { panic(err) } store := memory.NewStore() limiterInstance := limiter.New(store, rate) // Create Gin middleware middleware := ginmiddleware.NewMiddleware(limiterInstance) // Setup Gin router router := gin.Default() // Apply globally router.Use(middleware) // Or apply to specific routes router.GET("/api/data", middleware, func(c *gin.Context) { c.JSON(200, gin.H{"message": "success"}) }) // Rate limit headers are automatically added to responses router.Run(":8080") } ``` -------------------------------- ### Initialize Redis Store for Limiter Source: https://github.com/ulule/limiter/blob/master/README.md Initializes a Redis store for the Limiter library. This store will be used to persist rate limiting data. It accepts a Redis client and allows optional configuration for key prefix and retry attempts. ```go import "github.com/ulule/limiter/v3/drivers/store/redis" store, err := redis.NewStore(client) if err != nil { panic(err) } ``` ```go import "github.com/ulule/limiter/v3/drivers/store/redis" store, err := redis.NewStoreWithOptions(pool, limiter.StoreOptions{ Prefix: "your_own_prefix", }) if err != nil { panic(err) } ``` -------------------------------- ### Create Limiter Instance with Store and Rate Source: https://github.com/ulule/limiter/blob/master/README.md Creates a Limiter instance by combining a configured store and a rate limit rule. This instance is then used with various middleware implementations. Options can be provided to customize client IP header or IPv6 masking. ```go // Then, create the limiter instance which takes the store and the rate as arguments. // Now, you can give this instance to any supported middleware. instance := limiter.New(store, rate) ``` ```go // Alternatively, you can pass options to the limiter instance with several options. instance := limiter.New(store, rate, limiter.WithClientIPHeader("True-Client-IP"), limiter.WithIPv6Mask(mask)) ``` -------------------------------- ### Standard HTTP Middleware Integration (Go) Source: https://context7.com/ulule/limiter/llms.txt Integrates Limiter with Go's standard `net/http` package. It demonstrates creating a rate limiter, initializing the `stdlib` middleware, and wrapping an existing HTTP handler. The middleware automatically injects `X-RateLimit-*` headers and returns a `429 Too Many Requests` status when the limit is exceeded. Requires 'limiter/v3', 'limiter/v3/drivers/store/memory', and 'limiter/v3/drivers/middleware/stdlib'. ```go package main import ( "net/http" "time" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { // Create rate limiter: 10 requests per minute rate, err := limiter.NewRateFromFormatted("10-M") if err != nil { panic(err) } store := memory.NewStore() limiterInstance := limiter.New(store, rate) // Create middleware middleware := stdlib.NewMiddleware(limiterInstance) // Wrap your handler handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }) // Apply middleware http.Handle("/", middleware.Handler(handler)) // Server will return: // - 200 OK with headers when under limit // - 429 Too Many Requests when limit exceeded // Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset http.ListenAndServe(":8080", nil) } ``` -------------------------------- ### Create Rate from Formatted String (Go) Source: https://context7.com/ulule/limiter/llms.txt Shows how to parse rate limits from a simple string format (e.g., "-"). Supported periods include seconds (S), minutes (M), hours (H), and days (D). This simplifies configuration by allowing rates to be defined concisely. Requires the 'limiter/v3' package. ```go package main import ( "fmt" "github.com/ulule/limiter/v3" ) func main() { // Format: "-" // Periods: S (second), M (minute), H (hour), D (day) // 5 requests per second rate1, err := limiter.NewRateFromFormatted("5-S") if err != nil { panic(err) } fmt.Printf("Limit: %d, Period: %v\n", rate1.Limit, rate1.Period) // 1000 requests per hour rate2, err := limiter.NewRateFromFormatted("1000-H") if err != nil { panic(err) } // 2000 requests per day rate3, err := limiter.NewRateFromFormatted("2000-D") if err != nil { panic(err) } } ``` -------------------------------- ### Initialize In-Memory Store for Limiter Source: https://github.com/ulule/limiter/blob/master/README.md Initializes an in-memory store for the Limiter library. This store is suitable for development or simpler use cases and includes a background goroutine for clearing expired keys. ```go import "github.com/ulule/limiter/v3/drivers/store/memory" store := memory.NewStore() ``` -------------------------------- ### In-Memory Store Backend for Single-Instance Rate Limiting Source: https://context7.com/ulule/limiter/llms.txt Utilizes an in-memory storage backend for rate limiting in single-instance applications, eliminating external dependencies. This requires the `limiter` package and its `memory` store driver, along with the `stdlib` middleware. It allows configuration of cleanup intervals. ```go package main import ( "time" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" "net/http" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { // Create memory store with defaults store := memory.NewStore() // Or create with custom cleanup interval storeWithOpts := memory.NewStoreWithOptions(limiter.StoreOptions{ Prefix: "my_limiter", CleanUpInterval: 60 * time.Second, }) // Create rate limiter rate := limiter.Rate{ Period: 1 * time.Minute, Limit: 30, } limiterInstance := limiter.New(storeWithOpts, rate) // Use in middleware middleware := stdlib.NewMiddleware(limiterInstance) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("In-memory rate limiting")) }) http.ListenAndServe(":8080", middleware.Handler(handler)) } ``` -------------------------------- ### Redis Store Backend for Distributed Rate Limiting Source: https://context7.com/ulule/limiter/llms.txt Implements rate limiting using Redis as a distributed backend, enabling rate limiting across multiple servers. This requires the `redis` and `limiter` packages, along with the `redisstore` driver and `stdlib` middleware. It allows for custom store options like prefix and retry attempts. ```go package main import ( "context" "github.com/redis/go-redis/v9" "github.com/ulule/limiter/v3" redisstore "github.com/ulule/limiter/v3/drivers/store/redis" "net/http" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { // Create Redis client client := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, }) // Test connection _, err := client.Ping(context.Background()).Result() if err != nil { panic(err) } // Create Redis store with default options store, err := redisstore.NewStore(client) if err != nil { panic(err) } // Or create with custom options storeWithOpts, err := redisstore.NewStoreWithOptions(client, limiter.StoreOptions{ Prefix: "myapp_rate_limit", MaxRetry: 3, }) if err != nil { panic(err) } // Create limiter with Redis backend rate, _ := limiter.NewRateFromFormatted("1000-H") limiterInstance := limiter.New(storeWithOpts, rate) // Use in middleware middleware := stdlib.NewMiddleware(limiterInstance) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Distributed rate limiting")) }) http.ListenAndServe(":8080", middleware.Handler(handler)) } ``` -------------------------------- ### Peek Rate Limit Status in Go Source: https://context7.com/ulule/limiter/llms.txt Allows checking the current rate limit status for a client key without affecting the counter. This is useful for read-only checks or monitoring. It requires a context, the client key, and an initialized limiter instance. ```go package main import ( "context" "fmt" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { rate, _ := limiter.NewRateFromFormatted("10-H") store := memory.NewStore() limiterInstance := limiter.New(store, rate) ctx := context.Background() clientKey := "192.168.1.100" // Make some requests first limiterInstance.Get(ctx, clientKey) limiterInstance.Get(ctx, clientKey) limiterInstance.Get(ctx, clientKey) // Peek without incrementing limitContext, err := limiterInstance.Peek(ctx, clientKey) if err != nil { panic(err) } fmt.Printf("Current count: %d\n", limitContext.Limit - limitContext.Remaining) // 3 fmt.Printf("Remaining: %d\n", limitContext.Remaining) // 7 // Another peek doesn't change the count limitContext2, _ := limiterInstance.Peek(ctx, clientKey) fmt.Printf("Still remaining: %d\n", limitContext2.Remaining) // 7 } ``` -------------------------------- ### Define and Format Rate Limiter Rules Source: https://github.com/ulule/limiter/blob/master/README.md Defines a rate limiter rule by specifying the number of requests allowed within a given time period. Supports both explicit time.Duration and a simplified string format like '1000-H' for 1000 requests per hour. ```go // Create a rate with the given limit (number of requests) for the given // period (a time.Duration of your choice). import "github.com/ulule/limiter/v3" rate := limiter.Rate{ Period: 1 * time.Hour, Limit: 1000, } // You can also use the simplified format "-", with the given // periods: // // * "S": second // * "M": minute // * "H": hour // * "D": day // // Examples: // // * 5 reqs/second: "5-S" // * 10 reqs/minute: "10-M" // * 1000 reqs/hour: "1000-H" // * 2000 reqs/day: "2000-D" // rate, err := limiter.NewRateFromFormatted("1000-H") if err != nil { panic(err) } ``` -------------------------------- ### Custom Increment Values for Rate Limiting in Go Source: https://context7.com/ulule/limiter/llms.txt Supports incrementing rate limit counters by custom amounts, enabling weighted rate limiting where different actions consume different amounts of the limit. This is useful for differentiating between standard and resource-intensive operations. It requires a context, the client key, the increment amount, and an initialized limiter instance. ```go package main import ( "context" "fmt" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { rate, _ := limiter.NewRateFromFormatted("100-H") store := memory.NewStore() limiterInstance := limiter.New(store, rate) ctx := context.Background() apiKey := "api_key_xyz" // Regular request costs 1 limitContext, err := limiterInstance.Get(ctx, apiKey) if err != nil { panic(err) } fmt.Printf("After 1 request - Remaining: %d\n", limitContext.Remaining) // 99 // Heavy operation costs 10 requests limitContext, err = limiterInstance.Increment(ctx, apiKey, 10) if err != nil { panic(err) } fmt.Printf("After heavy operation - Remaining: %d\n", limitContext.Remaining) // 89 // Bulk operation costs 20 requests limitContext, err = limiterInstance.Increment(ctx, apiKey, 20) if err != nil { panic(err) } fmt.Printf("After bulk operation - Remaining: %d\n", limitContext.Remaining) // 69 } ``` -------------------------------- ### Extract Client IP from HTTP Requests in Go Source: https://context7.com/ulule/limiter/llms.txt Provides functionality to extract client IP addresses from incoming HTTP requests, with built-in support for trusting `X-Forwarded-For` and other proxy headers. It also allows for IP masking based on a CIDR mask for grouping IPs. This is crucial for accurate rate limiting in distributed or proxied environments. Requires an initialized limiter instance with appropriate options. ```go package main import ( "fmt" "net" "net/http" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" ) func main() { rate, _ := limiter.NewRateFromFormatted("100-H") store := memory.NewStore() // Create limiter with IP options mask := net.CIDRMask(24, 32) // Group by /24 subnet limiterInstance := limiter.New( store, rate, limiter.WithIPv4Mask(mask), limiter.WithTrustForwardHeader(true), ) // In your HTTP handler handler := func(w http.ResponseWriter, r *http.Request) { // Get raw IP ip := limiterInstance.GetIP(r) fmt.Printf("Client IP: %s\n", ip.String()) // Get IP with mask applied maskedIP := limiterInstance.GetIPWithMask(r) fmt.Printf("Masked IP: %s\n", maskedIP.String()) // Get IP as string key for rate limiting key := limiterInstance.GetIPKey(r) fmt.Printf("Rate limit key: %s\n", key) w.Write([]byte("OK")) } http.ListenAndServe(":8080", http.HandlerFunc(handler)) } ``` -------------------------------- ### Apply IPv4 and IPv6 Subnet Masking for Grouping Clients Source: https://context7.com/ulule/limiter/llms.txt This code snippet illustrates how to apply network masks (CIDR masks) to group clients by their IP subnet for broader rate limiting. It configures both IPv4 (/24) and IPv6 (/64) subnets, ensuring that all IPs within a subnet share a single rate limit. This is useful for managing traffic from large networks or IP ranges. Dependencies include the net, net/http, and limiter libraries. ```go package main import ( "net" "net/http" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/memory" "github.com/ulule/limiter/v3/drivers/middleware/stdlib" ) func main() { rate, _ := limiter.NewRateFromFormatted("100-H") store := memory.NewStore() // Group IPv4 by /24 subnet (256 addresses) ipv4Mask := net.CIDRMask(24, 32) // Group IPv6 by /64 subnet ipv6Mask := net.CIDRMask(64, 128) // Create limiter with masks limiterInstance := limiter.New( store, rate, limiter.WithIPv4Mask(ipv4Mask), limiter.WithIPv6Mask(ipv6Mask), ) // Now all IPs in 192.168.1.0/24 share the same rate limit // Example: 192.168.1.1, 192.168.1.2, 192.168.1.100 all count together middleware := stdlib.NewMiddleware(limiterInstance) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Subnet-based rate limiting")) }) http.ListenAndServe(":8080", middleware.Handler(handler)) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.