// Set makes a two-way binding between the given Goji request context and the // given go.net/context.Context. Returns the fresh context.Context that contains // this binding. Using the ToC and From functions will allow you to convert // between one and the other. // // Note that since context.Context's are immutable, you will have to call this // function to "re-bind" the request's canonical context.Context if you ever // decide to change it. func Set(c *web.C, context context.Context) context.Context { if c.Env == nil { c.Env = make(map[interface{}]interface{}) } ctx := ctx{c, context} c.Env[&ckey] = ctx return ctx }
// 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) }
// URLQuery is a middleware to parse the URL Query parameters just once, // and store the resulting url.Values in the context. func URLQuery(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if c.Env == nil { c.Env = make(map[interface{}]interface{}) } c.Env[URLQueryKey] = r.URL.Query() h.ServeHTTP(w, r) } return http.HandlerFunc(fn) }
// Use c.Env["FOO"] = "Bar" func SetupEnv(c *web.C, h http.Handler) http.Handler { handler := func(w http.ResponseWriter, r *http.Request) { if c.Env == nil { c.Env = make(map[interface{}]interface{}) } // Call the next handler h.ServeHTTP(w, r) } return http.HandlerFunc(handler) }
// 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) }
/* {{{ func EnvInit(c *web.C, h http.Handler) http.Handler * 初始化环境 */ func EnvInit(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { ac := new(Access) //access日志信息 ac.Time = time.Now() ac.Method = r.Method ac.URI = r.RequestURI ac.Proto = r.Proto ac.Host = r.Host ac.InHeader = &r.Header // env if c.Env == nil { //c.Env = make(map[string]interface{}) c.Env = make(map[interface{}]interface{}) } // make rand string(for debug, session...) buf := make([]byte, 16) randbo.New().Read(buf) //号称最快的随机字符串 ac.Session = fmt.Sprintf("%x", buf) c.Env[RequestIDKey] = ac.Session c.Env[LogPrefixKey] = "[" + ac.Session[:10] + "]" //只显示前十位 Trace("[%s] [%s %s] started", ac.Session[:10], r.Method, r.RequestURI) lw := utils.WrapWriter(w) pathPieces := strings.Split(r.URL.Path, "/") for off, piece := range pathPieces { if piece != "" { if off == 1 { c.Env[EndpointKey] = piece } if off == 2 && piece[0] != '@' { //@开头是selector c.Env[RowkeyKey] = piece } if off > 1 && piece[0] == '@' { c.Env[SelectorKey] = piece } } } // real ip(处理在代理服务器之后的情况) if rip := realIP(r); rip != "" { c.Env[OriginalRemoteAddrKey] = r.RemoteAddr r.RemoteAddr = rip } ac.IP = r.RemoteAddr //init RESTContext var rcErr error var rc *RESTContext rc, rcHolder, rcErr = RCHolder(*c, w, r) rc.Access = ac rc.Access.ReqLength = len(rc.RequestBody) if rcErr != nil { rc.RESTBadRequest(rcErr) return } h.ServeHTTP(lw, r) } return http.HandlerFunc(fn) }