// EnvInit is a middleware that allocates an environment map if one does not // already exist. This is necessary because Goji does not guarantee that Env is // present when running middleware (it avoids forcing the map allocation). Note // that other middleware should check Env for nil in order to maximize // compatibility (when EnvInit is not used, or when another middleware layer // blanks out Env), but for situations in which the user controls the middleware // stack and knows EnvInit is present, this middleware can eliminate a lot of // boilerplate. func EnvInit(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if c.Env == nil { c.Env = make(map[string]interface{}) } h.ServeHTTP(w, r) } return http.HandlerFunc(fn) }
// RequestID is a middleware that injects a request ID into the context of each // request. A request ID is a string of the form "host.example.com/random-0001", // where "random" is a base62 random string that uniquely identifies this go // process, and where the last number is an atomically incremented request // counter. func RequestID(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if c.Env == nil { c.Env = make(map[string]interface{}) } myid := atomic.AddUint64(&reqid, 1) c.Env[RequestIDKey] = fmt.Sprintf("%s-%06d", prefix, myid) h.ServeHTTP(w, r) } return http.HandlerFunc(fn) }
// RealIP is a middleware that sets a http.Request's RemoteAddr to the results // of parsing either the X-Forwarded-For header or the X-Real-IP header (in that // order). It places the original value of RemoteAddr in a context environment // variable. // // This middleware should be inserted fairly early in the middleware stack to // ensure that subsequent layers (e.g., request loggers) which examine the // RemoteAddr will see the intended value. // // You should only use this middleware if you can trust the headers passed to // you (in particular, the two headers this middleware uses), for example // because you have placed a reverse proxy like HAProxy or nginx in front of // Goji. If your reverse proxies are configured to pass along arbitrary header // values from the client, or if you use this middleware without a reverse // proxy, malicious clients will be able to make you very sad (or, depending on // how you're using RemoteAddr, vulnerable to an attack of some sort). func RealIP(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if rip := realIP(r); rip != "" { if c.Env == nil { c.Env = make(map[string]interface{}) } c.Env[OriginalRemoteAddrKey] = r.RemoteAddr r.RemoteAddr = rip } h.ServeHTTP(w, r) } return http.HandlerFunc(fn) }