github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/go-chi/chi/context.go (about) 1 package chi 2 3 import ( 4 "context" 5 "net" 6 "strings" 7 8 "github.com/hellobchain/newcryptosm/http" 9 ) 10 11 var ( 12 // RouteCtxKey is the context.Context key to store the request context. 13 RouteCtxKey = &contextKey{"RouteContext"} 14 ) 15 16 // Context is the default routing context set on the root node of a 17 // request context to track route patterns, URL parameters and 18 // an optional routing path. 19 type Context struct { 20 Routes Routes 21 22 // Routing path/method override used during the route search. 23 // See Mux#routeHTTP method. 24 RoutePath string 25 RouteMethod string 26 27 // Routing pattern stack throughout the lifecycle of the request, 28 // across all connected routers. It is a record of all matching 29 // patterns across a stack of sub-routers. 30 RoutePatterns []string 31 32 // URLParams are the stack of routeParams captured during the 33 // routing lifecycle across a stack of sub-routers. 34 URLParams RouteParams 35 36 // The endpoint routing pattern that matched the request URI path 37 // or `RoutePath` of the current sub-router. This value will update 38 // during the lifecycle of a request passing through a stack of 39 // sub-routers. 40 routePattern string 41 42 // Route parameters matched for the current sub-router. It is 43 // intentionally unexported so it cant be tampered. 44 routeParams RouteParams 45 46 // methodNotAllowed hint 47 methodNotAllowed bool 48 } 49 50 // NewRouteContext returns a new routing Context object. 51 func NewRouteContext() *Context { 52 return &Context{} 53 } 54 55 // Reset a routing context to its initial state. 56 func (x *Context) Reset() { 57 x.Routes = nil 58 x.RoutePath = "" 59 x.RouteMethod = "" 60 x.RoutePatterns = x.RoutePatterns[:0] 61 x.URLParams.Keys = x.URLParams.Keys[:0] 62 x.URLParams.Values = x.URLParams.Values[:0] 63 64 x.routePattern = "" 65 x.routeParams.Keys = x.routeParams.Keys[:0] 66 x.routeParams.Values = x.routeParams.Values[:0] 67 x.methodNotAllowed = false 68 } 69 70 // URLParam returns the corresponding URL parameter value from the request 71 // routing context. 72 func (x *Context) URLParam(key string) string { 73 for k := len(x.URLParams.Keys) - 1; k >= 0; k-- { 74 if x.URLParams.Keys[k] == key { 75 return x.URLParams.Values[k] 76 } 77 } 78 return "" 79 } 80 81 // RoutePattern builds the routing pattern string for the particular 82 // request, at the particular point during routing. This means, the value 83 // will change throughout the execution of a request in a router. That is 84 // why its advised to only use this value after calling the next handler. 85 // 86 // For example, 87 // 88 // func Instrument(next http.Handler) http.Handler { 89 // return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 90 // next.ServeHTTP(w, r) 91 // routePattern := chi.RouteContext(r.Context()).RoutePattern() 92 // measure(w, r, routePattern) 93 // }) 94 // } 95 func (x *Context) RoutePattern() string { 96 routePattern := strings.Join(x.RoutePatterns, "") 97 return strings.Replace(routePattern, "/*/", "/", -1) 98 } 99 100 // RouteContext returns chi's routing Context object from a 101 // http.Request Context. 102 func RouteContext(ctx context.Context) *Context { 103 return ctx.Value(RouteCtxKey).(*Context) 104 } 105 106 // URLParam returns the url parameter from a http.Request object. 107 func URLParam(r *http.Request, key string) string { 108 if rctx := RouteContext(r.Context()); rctx != nil { 109 return rctx.URLParam(key) 110 } 111 return "" 112 } 113 114 // URLParamFromCtx returns the url parameter from a http.Request Context. 115 func URLParamFromCtx(ctx context.Context, key string) string { 116 if rctx := RouteContext(ctx); rctx != nil { 117 return rctx.URLParam(key) 118 } 119 return "" 120 } 121 122 // RouteParams is a structure to track URL routing parameters efficiently. 123 type RouteParams struct { 124 Keys, Values []string 125 } 126 127 // Add will append a URL parameter to the end of the route param 128 func (s *RouteParams) Add(key, value string) { 129 (*s).Keys = append((*s).Keys, key) 130 (*s).Values = append((*s).Values, value) 131 } 132 133 // ServerBaseContext wraps an http.Handler to set the request context to the 134 // `baseCtx`. 135 func ServerBaseContext(baseCtx context.Context, h http.Handler) http.Handler { 136 fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 137 ctx := r.Context() 138 baseCtx := baseCtx 139 140 // Copy over default net/http server context keys 141 if v, ok := ctx.Value(http.ServerContextKey).(*http.Server); ok { 142 baseCtx = context.WithValue(baseCtx, http.ServerContextKey, v) 143 } 144 if v, ok := ctx.Value(http.LocalAddrContextKey).(net.Addr); ok { 145 baseCtx = context.WithValue(baseCtx, http.LocalAddrContextKey, v) 146 } 147 148 h.ServeHTTP(w, r.WithContext(baseCtx)) 149 }) 150 return fn 151 } 152 153 // contextKey is a value for use with context.WithValue. It's used as 154 // a pointer so it fits in an interface{} without allocation. This technique 155 // for defining context keys was copied from Go 1.7's new use of context in net/http. 156 type contextKey struct { 157 name string 158 } 159 160 func (k *contextKey) String() string { 161 return "chi context value " + k.name 162 }