1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
package stdlib
import (
"net/http"
"strconv"
"github.com/ulule/limiter/v3"
)
// Middleware is the middleware for basic http.Handler.
type Middleware struct {
Limiter *limiter.Limiter
OnError ErrorHandler
OnLimitReached LimitReachedHandler
TrustForwardHeader bool
}
// NewMiddleware return a new instance of a basic HTTP middleware.
func NewMiddleware(limiter *limiter.Limiter, options ...Option) *Middleware {
middleware := &Middleware{
Limiter: limiter,
OnError: DefaultErrorHandler,
OnLimitReached: DefaultLimitReachedHandler,
}
for _, option := range options {
option.apply(middleware)
}
return middleware
}
// Handler the middleware handler.
func (middleware *Middleware) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
context, err := middleware.Limiter.Get(r.Context(), middleware.Limiter.GetIPKey(r))
if err != nil {
middleware.OnError(w, r, err)
return
}
w.Header().Add("X-RateLimit-Limit", strconv.FormatInt(context.Limit, 10))
w.Header().Add("X-RateLimit-Remaining", strconv.FormatInt(context.Remaining, 10))
w.Header().Add("X-RateLimit-Reset", strconv.FormatInt(context.Reset, 10))
if context.Reached {
middleware.OnLimitReached(w, r)
return
}
h.ServeHTTP(w, r)
})
}
|