func setRateLimitHeaders(resp http.ResponseWriter, controller *controller, id string) {
	headers := resp.Header()
	headers.Set("X-RateLimit-Limit", strconv.FormatUint(controller.quota.Limit, 10))
	headers.Set("X-RateLimit-Reset", strconv.FormatInt(controller.RetryAt(id).Unix(), 10))
	headers.Set("X-RateLimit-Remaining", strconv.FormatUint(controller.RemainingLimit(id), 10))
}
Set Rate Limit Headers helper function
package throttle
import (
	"bytes"
	"encoding/json"
	"net"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"time"
)
const (
	StatusTooManyRequests = 429
	defaultStatusCode = StatusTooManyRequests
	defaultMessage = "Too Many Requests"
	defaultKeyPrefix = "throttle"
	forwardedForHeader = "X-FORWARDED-FOR"
	defaultDisabled = false
)
type Options struct {
	StatusCode int
	Message string
	IdentificationFunction func(*http.Request) string
	KeyPrefix string
	Store KeyValueStorer
	Disabled bool
}
type KeyValueStorer interface {
	Get(key string) ([]byte, error)
	Set(key string, value []byte) error
}
type Quota struct {
	Limit uint64
	Within time.Duration
}
func (q *Quota) KeyId() string {
	return strconv.FormatInt(int64(q.Within)/int64(q.Limit), 10)
}
type accessMessage struct {
	StatusCode int
	Message string
}
func newAccessMessage(statusCode int, message string) *accessMessage {
	return &accessMessage{
		StatusCode: statusCode,
		Message:    message,
	}
}
type accessCount struct {
	Count    uint64        `json:"count"`
	Start    time.Time     `json:"start"`
	Duration time.Duration `json:"duration"`
}
func (r accessCount) IsFresh() bool {
	return time.Now().UTC().Sub(r.Start) < r.Duration
}
func (r *accessCount) Increment() {
	if r.IsFresh() {
		r.Count++
	} else {
		r.Count = 1
		r.Start = time.Now().UTC()
	}
}
func (r *accessCount) GetCount() uint64 {
	if r.IsFresh() {
		return r.Count
	} else {
		return 0
	}
}
func newAccessCount(duration time.Duration) *accessCount {
	return &accessCount{
		0,
		time.Now().UTC(),
		duration,
	}
}
func accessCountFromBytes(accessCountBytes []byte) *accessCount {
	byteBufferString := bytes.NewBuffer(accessCountBytes)
	a := &accessCount{}
	if err := json.NewDecoder(byteBufferString).Decode(a); err != nil {
		panic(err.Error())
	}
	return a
}
type controller struct {
	*sync.Mutex
	quota *Quota
	store KeyValueStorer
}
func (c *controller) GetAccessCount(id string) (a *accessCount) {
	accessCountBytes, err := c.store.Get(id)
	if err == nil {
		a = accessCountFromBytes(accessCountBytes)
	} else {
		a = newAccessCount(c.quota.Within)
	}
	return a
}
func (c *controller) SetAccessCount(id string, a *accessCount) {
	marshalled, err := json.Marshal(a)
	if err != nil {
		panic(err.Error())
	}
	err = c.store.Set(id, marshalled)
	if err != nil {
		panic(err.Error())
	}
}
func (c *controller) RegisterAccess(id string) {
	c.Lock()
	defer c.Unlock()
	counter := c.GetAccessCount(id)
	counter.Increment()
	c.SetAccessCount(id, counter)
}
func (c *controller) DeniesAccess(id string) bool {
	counter := c.GetAccessCount(id)
	return counter.GetCount() >= c.quota.Limit
}
func (c *controller) RetryAt(id string) time.Time {
	counter := c.GetAccessCount(id)
	return counter.Start.Add(c.quota.Within)
}
func (c *controller) RemainingLimit(id string) uint64 {
	counter := c.GetAccessCount(id)
	return c.quota.Limit - counter.GetCount()
}
func newController(quota *Quota, store KeyValueStorer) *controller {
	return &controller{
		&sync.Mutex{},
		quota,
		store,
	}
}
func (o *Options) Identify(req *http.Request) string {
	return o.IdentificationFunction(req)
}
func Policy(quota *Quota, options ...*Options) func(resp http.ResponseWriter, req *http.Request) {
	o := newOptions(options)
	if o.Disabled {
		return func(resp http.ResponseWriter, req *http.Request) {}
	}
	controller := newController(quota, o.Store)
	return func(resp http.ResponseWriter, req *http.Request) {
		id := makeKey(o.KeyPrefix, quota.KeyId(), o.Identify(req))
		if controller.DeniesAccess(id) {
			msg := newAccessMessage(o.StatusCode, o.Message)
			setRateLimitHeaders(resp, controller, id)
			resp.WriteHeader(msg.StatusCode)
			resp.Write([]byte(msg.Message))
			return
		} else {
			controller.RegisterAccess(id)
			setRateLimitHeaders(resp, controller, id)
		}
	}
}