Documentation ¶
Overview ¶
Package httplimit provides middleware for rate limiting HTTP handlers.
The implementation is designed to work with Go's built-in http.Handler and http.HandlerFunc interfaces, so it will also work with any popular web frameworks that support middleware with these properties.
Index ¶
Examples ¶
Constants ¶
const ( // HeaderRateLimitLimit, HeaderRateLimitRemaining, and HeaderRateLimitReset // are the recommended return header values from IETF on rate limiting. Reset // is in UTC time. HeaderRateLimitLimit = "X-RateLimit-Limit" HeaderRateLimitRemaining = "X-RateLimit-Remaining" HeaderRateLimitReset = "X-RateLimit-Reset" // HeaderRetryAfter is the header used to indicate when a client should retry // requests (when the rate limit expires), in UTC time. HeaderRetryAfter = "Retry-After" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type KeyFunc ¶
KeyFunc is a function that accepts an http request and returns a string key that uniquely identifies this request for the purpose of rate limiting.
KeyFuncs are called on each request, so be mindful of performance and implement caching where possible. If a KeyFunc returns an error, the HTTP handler will return Internal Server Error and will NOT take from the limiter store.
Example (Custom) ¶
package main import ( "crypto/sha512" "encoding/base64" "net/http" "github.com/sethvargo/go-limiter/httplimit" ) var keyFunc httplimit.KeyFunc func main() { // This is an example KeyFunc that rate limits using the value from the // X-API-Key header. Since this value is likely a secret, it is hashed before // passing along to the store. keyFunc = httplimit.KeyFunc(func(r *http.Request) (string, error) { dig := sha512.Sum512([]byte(r.Header.Get("X-Token"))) return base64.StdEncoding.EncodeToString(dig[:]), nil }) // middleware, err := httplimit.NewMiddleware(store, keyFunc) }
Output:
func IPKeyFunc ¶
IPKeyFunc returns a function that keys data based on the incoming requests IP address. By default this uses the RemoteAddr, but you can also specify a list of headers which will be checked for an IP address first (e.g. "X-Forwarded-For"). Headers are retrieved using Header.Get(), which means they are case insensitive.
Example (Headers) ¶
package main import ( "github.com/sethvargo/go-limiter/httplimit" ) var keyFunc httplimit.KeyFunc func main() { keyFunc = httplimit.IPKeyFunc("X-Forwarded-For") // middleware, err := httplimit.NewMiddleware(store, keyFunc) }
Output:
type Middleware ¶
type Middleware struct {
// contains filtered or unexported fields
}
Middleware is a handler/mux that can wrap other middlware to implement HTTP rate limiting. It can rate limit based on an arbitrary KeyFunc, and supports anything that implements limiter.StoreWithContext.
func NewMiddleware ¶
func NewMiddleware(s limiter.Store, f KeyFunc) (*Middleware, error)
NewMiddleware creates a new middleware suitable for use as an HTTP handler. This function returns an error if either the Store or KeyFunc are nil.
Example ¶
package main import ( "fmt" "log" "net/http" "time" "github.com/sethvargo/go-limiter/httplimit" "github.com/sethvargo/go-limiter/memorystore" ) func main() { // Create a store that allows 30 requests per minute. store, err := memorystore.New(&memorystore.Config{ Tokens: 30, Interval: time.Minute, }) if err != nil { log.Fatal(err) } // Create the HTTP middleware from the store, keying by IP address. middleware, err := httplimit.NewMiddleware(store, httplimit.IPKeyFunc()) if err != nil { log.Fatal(err) } doWork := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) fmt.Fprintf(w, "hello world") }) // Wrap an individual handler (only rate limits this endpoint). mux1 := http.NewServeMux() mux1.Handle("/foo", middleware.Handle(doWork)) // rate limited mux1.Handle("/bar", doWork) // not rate limited _ = mux1 // Or wrap the entire mux (rate limits all endpoints). mux2 := http.NewServeMux() mux2.Handle("/foo", doWork) mux2.Handle("/bar", doWork) router := middleware.Handle(mux2) // all endpoints are rate limited _ = router }
Output:
func (*Middleware) Handle ¶
func (m *Middleware) Handle(next http.Handler) http.Handler
Handle returns the HTTP handler as a middleware. This handler calls Take() on the store and sets the common rate limiting headers. If the take is successful, the remaining middleware is called. If take is unsuccessful, the middleware chain is halted and the function renders a 429 to the caller with metadata about when it's safe to retry.