Skip to content

Commit 9a538f0

Browse files
author
Olivier Poitrey
committed
Refactor parameters API
1 parent 0f8b338 commit 9a538f0

File tree

7 files changed

+49
-67
lines changed

7 files changed

+49
-67
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func main() {
104104

105105
// Use c.Handler to terminate the chain with your final handler
106106
mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
107-
fmt.Fprintf(w, "Welcome %s!", xmux.URLParams(ctx).Get("name"))
107+
fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
108108
}))
109109

110110
if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {

xmux/mux.go

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// }
2121
//
2222
// func Hello(ctx context.Context, w http.ResponseWriter, r *http.Request) {
23-
// fmt.Fprintf(w, "hello, %s!\n", xmux.URLParams(ctx).Get("name"))
23+
// fmt.Fprintf(w, "hello, %s!\n", xmux.Params(ctx).Get("name"))
2424
// }
2525
//
2626
// func main() {
@@ -65,8 +65,8 @@
6565
// /files no match, but the router would redirect
6666
//
6767
// The value of parameters is saved as aParams type saved into the context.
68-
// Parameters can be retrieved by name using xhandler.URLParams(ctx).Get(name) method:
69-
// user := xhandler.URLParams(ctx).Get("user") // defined by :user or *user
68+
// Parameters can be retrieved by name using xhandler.Params(ctx).Get(name) method:
69+
// user := xhandler.Params(ctx).Get("user") // defined by :user or *user
7070
package xmux
7171

7272
import (
@@ -125,17 +125,19 @@ type Mux struct {
125125
PanicHandler func(context.Context, http.ResponseWriter, *http.Request, interface{})
126126
}
127127

128-
// Params holds URL parameters.
129-
type Params struct {
130-
params []struct {
131-
key string
132-
value string
133-
}
128+
// ParamHolder holds URL parameters.
129+
type ParamHolder struct {
130+
params []param
131+
}
132+
133+
type param struct {
134+
key string
135+
value string
134136
}
135137

136138
// Get returns the value of the first Param which key matches the given name.
137139
// If no matching Param is found, an empty string is returned.
138-
func (ps Params) Get(name string) string {
140+
func (ps ParamHolder) Get(name string) string {
139141
for i := range ps.params {
140142
if ps.params[i].key == name {
141143
return ps.params[i].value
@@ -146,20 +148,20 @@ func (ps Params) Get(name string) string {
146148

147149
type key int
148150

149-
const paramKey key = iota
151+
const paramsKey key = iota
150152

151-
var emptyParams = Params{}
153+
var emptyParams = ParamHolder{}
152154

153-
func newParamContext(ctx context.Context, p Params) context.Context {
154-
return context.WithValue(ctx, paramKey, p)
155+
func newParamContext(ctx context.Context, p ParamHolder) context.Context {
156+
return context.WithValue(ctx, paramsKey, p)
155157
}
156158

157-
// URLParams returns URL parameters stored in context
158-
func URLParams(ctx context.Context) Params {
159+
// Params returns URL parameters stored in context
160+
func Params(ctx context.Context) ParamHolder {
159161
if ctx == nil {
160162
return emptyParams
161163
}
162-
if p, ok := ctx.Value(paramKey).(Params); ok {
164+
if p, ok := ctx.Value(paramsKey).(ParamHolder); ok {
163165
return p
164166
}
165167
return emptyParams
@@ -246,7 +248,7 @@ func (mux *Mux) recv(ctx context.Context, w http.ResponseWriter, r *http.Request
246248
// If the path was found, it returns the handle function and the path parameter
247249
// values. Otherwise the third return value indicates whether a redirection to
248250
// the same path with an extra / without the trailing slash should be performed.
249-
func (mux *Mux) Lookup(method, path string) (xhandler.HandlerC, Params, bool) {
251+
func (mux *Mux) Lookup(method, path string) (xhandler.HandlerC, ParamHolder, bool) {
250252
if root := mux.trees[method]; root != nil {
251253
return root.getValue(path)
252254
}

xmux/mux_bench_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type route struct {
2525
var httpHandlerC = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {})
2626

2727
var xhandlerWrite = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
28-
io.WriteString(w, URLParams(ctx).Get("name"))
28+
io.WriteString(w, Params(ctx).Get("name"))
2929
})
3030

3131
func loadXhandler(routes []route) xhandler.HandlerC {

xmux/mux_example_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func ExampleMux() {
2424

2525
// Use c.Handler to terminate the chain with your final handler
2626
mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
27-
fmt.Fprintf(w, "Welcome %s!", xmux.URLParams(ctx).Get("name"))
27+
fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
2828
}))
2929

3030
if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {

xmux/mux_test.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,8 @@ func (m *mockResponseWriter) WriteString(s string) (n int, err error) {
2929
func (m *mockResponseWriter) WriteHeader(int) {}
3030

3131
func TestParams(t *testing.T) {
32-
ps := Params{
33-
params: []struct {
34-
key string
35-
value string
36-
}{
32+
ps := ParamHolder{
33+
params: []param{
3734
{"param1", "value1"},
3835
{"param2", "value2"},
3936
{"param3", "value3"},
@@ -46,31 +43,23 @@ func TestParams(t *testing.T) {
4643
}
4744

4845
func TestParamsDup(t *testing.T) {
49-
ps := Params{
50-
params: []struct {
51-
key string
52-
value string
53-
}{
46+
ps := ParamHolder{
47+
params: []param{
5448
{"param", "value1"},
5549
{"param", "value2"},
5650
},
5751
}
5852
assert.Equal(t, "value1", ps.Get("param"))
5953
}
6054

61-
func TestURLParams(t *testing.T) {
62-
ps := Params{
63-
params: []struct {
64-
key string
65-
value string
66-
}{
67-
{"param1", "value1"},
68-
},
55+
func TestCtxParams(t *testing.T) {
56+
ps := ParamHolder{
57+
params: []param{{"param1", "value1"}},
6958
}
7059
ctx := newParamContext(context.TODO(), ps)
71-
assert.Equal(t, "value1", URLParams(ctx).Get("param1"))
72-
assert.Equal(t, emptyParams, URLParams(context.TODO()))
73-
assert.Equal(t, emptyParams, URLParams(nil))
60+
assert.Equal(t, "value1", Params(ctx).Get("param1"))
61+
assert.Equal(t, emptyParams, Params(context.TODO()))
62+
assert.Equal(t, emptyParams, Params(nil))
7463
}
7564

7665
func TestMux(t *testing.T) {
@@ -79,10 +68,7 @@ func TestMux(t *testing.T) {
7968
routed := false
8069
mux.Handle("GET", "/user/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
8170
routed = true
82-
assert.Equal(t, Params{params: []struct {
83-
key string
84-
value string
85-
}{{"name", "gopher"}}}, URLParams(ctx))
71+
assert.Equal(t, ParamHolder{params: []param{{"name", "gopher"}}}, Params(ctx))
8672
}))
8773

8874
w := new(mockResponseWriter)

xmux/tree.go

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type nodeType uint8
3939
const (
4040
static nodeType = iota // default
4141
root
42-
param
42+
parameter
4343
catchAll
4444
)
4545

@@ -161,7 +161,7 @@ func (n *node) addRoute(path string, handler xhandler.HandlerC) {
161161
c := path[0]
162162

163163
// slash after param
164-
if n.nType == param && c == '/' && len(n.children) == 1 {
164+
if n.nType == parameter && c == '/' && len(n.children) == 1 {
165165
n = n.children[0]
166166
n.priority++
167167
continue walk
@@ -247,7 +247,7 @@ func (n *node) insertChild(numParams uint8, path, fullPath string, handler xhand
247247
}
248248

249249
child := &node{
250-
nType: param,
250+
nType: parameter,
251251
maxParams: numParams,
252252
}
253253
n.children = []*node{child}
@@ -322,13 +322,13 @@ func (n *node) insertChild(numParams uint8, path, fullPath string, handler xhand
322322
// If no handle can be found, a TSR (trailing slash redirect) recommendation is
323323
// made if a handler exists with an extra (without the) trailing slash for the
324324
// given path.
325-
func (n *node) getValue(path string) (handler xhandler.HandlerC, p Params, tsr bool) {
325+
func (n *node) getValue(path string) (handler xhandler.HandlerC, p ParamHolder, tsr bool) {
326326
walk: // Outer loop for walking the tree
327327
for {
328328
if len(path) > len(n.path) {
329329
if path[:len(n.path)] == n.path {
330330
path = path[len(n.path):]
331-
// If this node does not have a wildcard (param or catchAll)
331+
// If this node does not have a wildcard (parameter or catchAll)
332332
// child, we can just look up the next child node and continue
333333
// to walk down the tree
334334
if !n.wildChild {
@@ -351,8 +351,8 @@ walk: // Outer loop for walking the tree
351351
// handle wildcard child
352352
n = n.children[0]
353353
switch n.nType {
354-
case param:
355-
// find param end (either '/' or path end)
354+
case parameter:
355+
// find parameter end (either '/' or path end)
356356
end := 0
357357
for end < len(path) && path[end] != '/' {
358358
end++
@@ -361,10 +361,7 @@ walk: // Outer loop for walking the tree
361361
// save param value
362362
if p.params == nil {
363363
// lazy allocation
364-
p.params = make([]struct {
365-
key string
366-
value string
367-
}, 0, n.maxParams)
364+
p.params = make([]param, 0, n.maxParams)
368365
}
369366
i := len(p.params)
370367
p.params = p.params[:i+1] // expand slice within preallocated capacity
@@ -405,10 +402,7 @@ walk: // Outer loop for walking the tree
405402
// save param value
406403
if p.params == nil {
407404
// lazy allocation
408-
p.params = make([]struct {
409-
key string
410-
value string
411-
}, 0, n.maxParams)
405+
p.params = make([]param, 0, n.maxParams)
412406
}
413407
i := len(p.params)
414408
p.params = p.params[:i+1] // expand slice within preallocated capacity
@@ -469,7 +463,7 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
469463
ciPath = append(ciPath, n.path...)
470464

471465
if len(path) > 0 {
472-
// If this node does not have a wildcard (param or catchAll) child,
466+
// If this node does not have a wildcard (parameter or catchAll) child,
473467
// we can just look up the next child node and continue to walk down
474468
// the tree
475469
if !n.wildChild {
@@ -493,14 +487,14 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
493487

494488
n = n.children[0]
495489
switch n.nType {
496-
case param:
497-
// find param end (either '/' or path end)
490+
case parameter:
491+
// find parameter end (either '/' or path end)
498492
k := 0
499493
for k < len(path) && path[k] != '/' {
500494
k++
501495
}
502496

503-
// add param value to case insensitive path
497+
// add parameter value to case insensitive path
504498
ciPath = append(ciPath, path[:k]...)
505499

506500
// we need to go deeper!

xmux/tree_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ type testRequests []struct {
4242
path string
4343
nilHandler bool
4444
route string
45-
ps Params
45+
ps ParamHolder
4646
}
4747

4848
func checkRequests(t *testing.T, tree *node, requests testRequests) {
@@ -158,7 +158,7 @@ func TestTreeAddAndGet(t *testing.T) {
158158
checkMaxParams(t, tree)
159159
}
160160

161-
func newParams(kv ...string) (ps Params) {
161+
func newParams(kv ...string) (ps ParamHolder) {
162162
for i, l := 0, len(kv); i < l; i += 2 {
163163
ps.params = append(ps.params, struct {
164164
key string

0 commit comments

Comments
 (0)