...
1 package chi
2
3 import (
4 "context"
5 "net"
6 "net/http"
7 "strings"
8 )
9
10
11 func URLParam(r *http.Request, key string) string {
12 if rctx := RouteContext(r.Context()); rctx != nil {
13 return rctx.URLParam(key)
14 }
15 return ""
16 }
17
18
19 func URLParamFromCtx(ctx context.Context, key string) string {
20 if rctx := RouteContext(ctx); rctx != nil {
21 return rctx.URLParam(key)
22 }
23 return ""
24 }
25
26
27
28 func RouteContext(ctx context.Context) *Context {
29 val, _ := ctx.Value(RouteCtxKey).(*Context)
30 return val
31 }
32
33
34
35 func ServerBaseContext(baseCtx context.Context, h http.Handler) http.Handler {
36 fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
37 ctx := r.Context()
38 baseCtx := baseCtx
39
40
41 if v, ok := ctx.Value(http.ServerContextKey).(*http.Server); ok {
42 baseCtx = context.WithValue(baseCtx, http.ServerContextKey, v)
43 }
44 if v, ok := ctx.Value(http.LocalAddrContextKey).(net.Addr); ok {
45 baseCtx = context.WithValue(baseCtx, http.LocalAddrContextKey, v)
46 }
47
48 h.ServeHTTP(w, r.WithContext(baseCtx))
49 })
50 return fn
51 }
52
53
54 func NewRouteContext() *Context {
55 return &Context{}
56 }
57
58 var (
59
60 RouteCtxKey = &contextKey{"RouteContext"}
61 )
62
63
64
65
66 type Context struct {
67 Routes Routes
68
69
70
71 RoutePath string
72 RouteMethod string
73
74
75
76
77 RoutePatterns []string
78
79
80
81 URLParams RouteParams
82
83
84
85
86
87 routePattern string
88
89
90
91 routeParams RouteParams
92
93
94 methodNotAllowed bool
95 }
96
97
98 func (x *Context) Reset() {
99 x.Routes = nil
100 x.RoutePath = ""
101 x.RouteMethod = ""
102 x.RoutePatterns = x.RoutePatterns[:0]
103 x.URLParams.Keys = x.URLParams.Keys[:0]
104 x.URLParams.Values = x.URLParams.Values[:0]
105
106 x.routePattern = ""
107 x.routeParams.Keys = x.routeParams.Keys[:0]
108 x.routeParams.Values = x.routeParams.Values[:0]
109 x.methodNotAllowed = false
110 }
111
112
113
114 func (x *Context) URLParam(key string) string {
115 for k := len(x.URLParams.Keys) - 1; k >= 0; k-- {
116 if x.URLParams.Keys[k] == key {
117 return x.URLParams.Values[k]
118 }
119 }
120 return ""
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 func (x *Context) RoutePattern() string {
138 routePattern := strings.Join(x.RoutePatterns, "")
139 return replaceWildcards(routePattern)
140 }
141
142
143
144 func replaceWildcards(p string) string {
145 if strings.Contains(p, "/*/") {
146 return replaceWildcards(strings.Replace(p, "/*/", "/", -1))
147 }
148
149 return p
150 }
151
152
153 type RouteParams struct {
154 Keys, Values []string
155 }
156
157
158 func (s *RouteParams) Add(key, value string) {
159 s.Keys = append(s.Keys, key)
160 s.Values = append(s.Values, value)
161 }
162
163
164
165
166 type contextKey struct {
167 name string
168 }
169
170 func (k *contextKey) String() string {
171 return "chi context value " + k.name
172 }
173
View as plain text