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,
	}
}
WithRequest places the request on the context. The context of the request
is assigned a unique id, available at "http.request.id". The request itself
is available at "http.request". Other common attributes are available under
the prefix "http.request.". If a request is already present on the context,
this method will panic.
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
}