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  }