func (l *Limiter) GetBasicAuthUsers() []string {
	return l.basicAuthUsers.Keys()
}
GetBasicAuthUsers is thread-safe way of getting list of basic auth usernames to limit.
package limiter
import (
	"net/http"
	"sync"
	"time"
	cache "github.com/go-pkgz/expirable-cache"
	"golang.org/x/time/rate"
)
func New(generalExpirableOptions *ExpirableOptions) *Limiter {
	lmt := &Limiter{}
	lmt.SetMessageContentType("text/plain; charset=utf-8").
		SetMessage("You have reached maximum request limit.").
		SetStatusCode(429).
		SetOnLimitReached(nil).
		SetIPLookups([]string{"RemoteAddr", "X-Forwarded-For", "X-Real-IP"}).
		SetForwardedForIndexFromBehind(0).
		SetHeaders(make(map[string][]string)).
		SetContextValues(make(map[string][]string)).
		SetIgnoreURL(false)
	if generalExpirableOptions != nil {
		lmt.generalExpirableOptions = generalExpirableOptions
	} else {
		lmt.generalExpirableOptions = &ExpirableOptions{}
	}
	if lmt.generalExpirableOptions.DefaultExpirationTTL <= 0 {
		lmt.generalExpirableOptions.DefaultExpirationTTL = 87600 * time.Hour
	}
	lmt.tokenBuckets, _ = cache.NewCache(cache.TTL(lmt.generalExpirableOptions.DefaultExpirationTTL))
	lmt.basicAuthUsers, _ = cache.NewCache(cache.TTL(lmt.generalExpirableOptions.DefaultExpirationTTL))
	return lmt
}
type Limiter struct {
	max float64
	burst int
	message string
	messageContentType string
	statusCode int
	onLimitReached func(w http.ResponseWriter, r *http.Request)
	overrideDefaultResponseWriter bool
	ipLookups []string
	forwardedForIndex int
	methods []string
	generalExpirableOptions *ExpirableOptions
	basicAuthUsers cache.Cache
	headers map[string]cache.Cache
	contextValues map[string]cache.Cache
	tokenBuckets cache.Cache
	ignoreURL bool
	tokenBucketExpirationTTL  time.Duration
	basicAuthExpirationTTL    time.Duration
	headerEntryExpirationTTL  time.Duration
	contextEntryExpirationTTL time.Duration
	sync.RWMutex
}
func (l *Limiter) SetTokenBucketExpirationTTL(ttl time.Duration) *Limiter {
	l.Lock()
	l.tokenBucketExpirationTTL = ttl
	l.Unlock()
	return l
}
func (l *Limiter) GetTokenBucketExpirationTTL() time.Duration {
	l.RLock()
	defer l.RUnlock()
	return l.tokenBucketExpirationTTL
}
func (l *Limiter) SetBasicAuthExpirationTTL(ttl time.Duration) *Limiter {
	l.Lock()
	l.basicAuthExpirationTTL = ttl
	l.Unlock()
	return l
}
func (l *Limiter) GetBasicAuthExpirationTTL() time.Duration {
	l.RLock()
	defer l.RUnlock()
	return l.basicAuthExpirationTTL
}
func (l *Limiter) SetHeaderEntryExpirationTTL(ttl time.Duration) *Limiter {
	l.Lock()
	l.headerEntryExpirationTTL = ttl
	l.Unlock()
	return l
}
func (l *Limiter) GetHeaderEntryExpirationTTL() time.Duration {
	l.RLock()
	defer l.RUnlock()
	return l.headerEntryExpirationTTL
}
func (l *Limiter) SetContextValueEntryExpirationTTL(ttl time.Duration) *Limiter {
	l.Lock()
	l.contextEntryExpirationTTL = ttl
	l.Unlock()
	return l
}
func (l *Limiter) GetContextValueEntryExpirationTTL() time.Duration {
	l.RLock()
	defer l.RUnlock()
	return l.contextEntryExpirationTTL
}
func (l *Limiter) SetMax(max float64) *Limiter {
	l.Lock()
	l.max = max
	l.Unlock()
	return l
}
func (l *Limiter) GetMax() float64 {
	l.RLock()
	defer l.RUnlock()
	return l.max
}
func (l *Limiter) SetBurst(burst int) *Limiter {
	l.Lock()
	l.burst = burst
	l.Unlock()
	return l
}
func (l *Limiter) GetBurst() int {
	l.RLock()
	defer l.RUnlock()
	return l.burst
}
func (l *Limiter) SetMessage(msg string) *Limiter {
	l.Lock()
	l.message = msg
	l.Unlock()
	return l
}
func (l *Limiter) GetMessage() string {
	l.RLock()
	defer l.RUnlock()
	return l.message
}
func (l *Limiter) SetMessageContentType(contentType string) *Limiter {
	l.Lock()
	l.messageContentType = contentType
	l.Unlock()
	return l
}
func (l *Limiter) GetMessageContentType() string {
	l.RLock()
	defer l.RUnlock()
	return l.messageContentType
}
func (l *Limiter) SetStatusCode(statusCode int) *Limiter {
	l.Lock()
	l.statusCode = statusCode
	l.Unlock()
	return l
}
func (l *Limiter) GetStatusCode() int {
	l.RLock()
	defer l.RUnlock()
	return l.statusCode
}
func (l *Limiter) SetOnLimitReached(fn func(w http.ResponseWriter, r *http.Request)) *Limiter {
	l.Lock()
	l.onLimitReached = fn
	l.Unlock()
	return l
}
func (l *Limiter) ExecOnLimitReached(w http.ResponseWriter, r *http.Request) {
	l.RLock()
	defer l.RUnlock()
	fn := l.onLimitReached
	if fn != nil {
		fn(w, r)
	}
}
func (l *Limiter) SetOverrideDefaultResponseWriter(override bool) {
	l.Lock()
	l.overrideDefaultResponseWriter = override
	l.Unlock()
}
func (l *Limiter) GetOverrideDefaultResponseWriter() bool {
	l.RLock()
	defer l.RUnlock()
	return l.overrideDefaultResponseWriter
}
func (l *Limiter) SetIPLookups(ipLookups []string) *Limiter {
	l.Lock()
	l.ipLookups = ipLookups
	l.Unlock()
	return l
}
func (l *Limiter) GetIPLookups() []string {
	l.RLock()
	defer l.RUnlock()
	return l.ipLookups
}
func (l *Limiter) SetIgnoreURL(enabled bool) *Limiter {
	l.Lock()
	l.ignoreURL = enabled
	l.Unlock()
	return l
}
func (l *Limiter) GetIgnoreURL() bool {
	l.RLock()
	defer l.RUnlock()
	return l.ignoreURL
}
func (l *Limiter) SetForwardedForIndexFromBehind(forwardedForIndex int) *Limiter {
	l.Lock()
	l.forwardedForIndex = forwardedForIndex
	l.Unlock()
	return l
}
func (l *Limiter) GetForwardedForIndexFromBehind() int {
	l.RLock()
	defer l.RUnlock()
	return l.forwardedForIndex
}
func (l *Limiter) SetMethods(methods []string) *Limiter {
	l.Lock()
	l.methods = methods
	l.Unlock()
	return l
}
func (l *Limiter) GetMethods() []string {
	l.RLock()
	defer l.RUnlock()
	return l.methods
}
func (l *Limiter) SetBasicAuthUsers(basicAuthUsers []string) *Limiter {
	ttl := l.GetBasicAuthExpirationTTL()
	if ttl <= 0 {
		ttl = l.generalExpirableOptions.DefaultExpirationTTL
	}
	for _, basicAuthUser := range basicAuthUsers {
		l.basicAuthUsers.Set(basicAuthUser, true, ttl)
	}
	return l
}