func LimitFuncHandler(limiter *config.Limiter, nextFunc func(http.ResponseWriter, *http.Request)) http.Handler {
	return LimitHandler(limiter, http.HandlerFunc(nextFunc))
}
LimitFuncHandler is a middleware that performs rate-limiting given request handler function.
package main
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math"
	"net"
	"net/http"
	"strings"
	"time"
	"github.com/didip/tollbooth"
	"github.com/didip/tollbooth/config"
	log "github.com/sirupsen/logrus"
)
type Server struct {
	dispatch *Dispatch
}
func NewServer(dispatch *Dispatch, limitMax int64, limitTTL time.Duration) *Server {
	s := new(Server)
	s.dispatch = dispatch
	if limitMax != math.MaxInt64 {
		log.Infof("setting webserver rate-limit to %d/%s", limitMax, limitTTL)
		limiter := tollbooth.NewLimiter(limitMax, limitTTL)
		limiter.IPLookups = []string{"X-Forwarded-For", "RemoteAddr", "X-Real-IP"}
		limiter.Methods = []string{"POST"}
		http.Handle("/send", LimitFuncHandler(limiter, send))
	} else {
		http.HandleFunc("/send", send)
	}
	http.HandleFunc("/", defaultAction)
	return s
}
func (s Server) Run(address string) {
	log.Infof("starting webserver on %s", address)
	log.Fatal(http.ListenAndServe(address, WriteLogHandler(http.DefaultServeMux)))
}
type statusWriter struct {
	http.ResponseWriter
	statusCode int
	length     int
}
func (w *statusWriter) WriteHeader(status int) {
	w.statusCode = status
	w.ResponseWriter.WriteHeader(status)
}
func (w *statusWriter) Write(b []byte) (int, error) {
	if w.statusCode == 0 {
		w.statusCode = 200
	}
	w.length = len(b)
	return w.ResponseWriter.Write(b)
}
func WriteLogHandler(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		writer := statusWriter{w, 0, 0}
		t := time.Now()
		handler.ServeHTTP(&writer, r)
		latency := time.Since(t)
		clientIP := getClientIP(r)
		statusCode := writer.statusCode
		path := r.URL.Path
		method := r.Method
		log.Printf("%s - %s %s %d %v", clientIP, method, path, statusCode, latency)
	})
}
func LimitHandler(limiter *config.Limiter, next http.Handler) http.Handler {
	middle := func(w http.ResponseWriter, r *http.Request) {
		tollbooth.SetResponseHeaders(limiter, w)
		httpError := tollbooth.LimitByRequest(limiter, r)
		if httpError != nil {
			respondError(w, r, httpError.StatusCode, httpError.Message)
			return
		}
		next.ServeHTTP(w, r)
	}
	return http.HandlerFunc(middle)
}