func WithVars(ctx Context, r *http.Request) Context {
	return &muxVarsContext{
		Context: ctx,
		vars:    getVarsFromRequest(r),
	}
}
WithVars extracts gorilla/mux vars and makes them available on the returned
context. Variables are available at keys with the prefix "vars.". For
example, if looking for the variable "name", it can be accessed as
"vars.name". Implementations that are accessing values need not know that
the underlying context is implemented with gorilla/mux vars.
package context
import (
	"errors"
	"net"
	"net/http"
	"strings"
	"sync"
	"time"
	log "github.com/Sirupsen/logrus"
	"github.com/docker/distribution/uuid"
	"github.com/gorilla/mux"
)
var (
	ErrNoRequestContext        = errors.New("no http request in context")
	ErrNoResponseWriterContext = errors.New("no http response in context")
)
func parseIP(ipStr string) net.IP {
	ip := net.ParseIP(ipStr)
	if ip == nil {
		log.Warnf("invalid remote IP address: %q", ipStr)
	}
	return ip
}
func RemoteAddr(r *http.Request) string {
	if prior := r.Header.Get("X-Forwarded-For"); prior != "" {
		proxies := strings.Split(prior, ",")
		if len(proxies) > 0 {
			remoteAddr := strings.Trim(proxies[0], " ")
			if parseIP(remoteAddr) != nil {
				return remoteAddr
			}
		}
	}
	if realIP := r.Header.Get("X-Real-Ip"); realIP != "" {
		if parseIP(realIP) != nil {
			return realIP
		}
	}
	return r.RemoteAddr
}
func RemoteIP(r *http.Request) string {
	addr := RemoteAddr(r)
	if ip, _, err := net.SplitHostPort(addr); err == nil {
		return ip
	}
	return addr
}
func WithRequest(ctx Context, r *http.Request) Context {
	if ctx.Value("http.request") != nil {
		panic("only one request per context")
	}
	return &httpRequestContext{
		Context:   ctx,
		startedAt: time.Now(),
		id:        uuid.Generate().String(),
		r:         r,
	}
}
func GetRequest(ctx Context) (*http.Request, error) {
	if r, ok := ctx.Value("http.request").(*http.Request); r != nil && ok {
		return r, nil
	}
	return nil, ErrNoRequestContext
}
func GetRequestID(ctx Context) string {
	return GetStringValue(ctx, "http.request.id")
}
func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.ResponseWriter) {
	if closeNotifier, ok := w.(http.CloseNotifier); ok {
		irwCN := &instrumentedResponseWriterCN{
			instrumentedResponseWriter: instrumentedResponseWriter{
				ResponseWriter: w,
				Context:        ctx,
			},
			CloseNotifier: closeNotifier,
		}
		return irwCN, irwCN
	}
	irw := instrumentedResponseWriter{
		ResponseWriter: w,
		Context:        ctx,
	}
	return &irw, &irw
}
func GetResponseWriter(ctx Context) (http.ResponseWriter, error) {
	v := ctx.Value("http.response")
	rw, ok := v.(http.ResponseWriter)
	if !ok || rw == nil {
		return nil, ErrNoResponseWriterContext
	}
	return rw, nil
}
var getVarsFromRequest = mux.Vars