Browse Source

Convert Context to interface

Wijnand Modderman-Lenstra 2 years ago
parent
commit
359e1ab3f7
9 changed files with 245 additions and 192 deletions
  1. 2
    2
      chain.go
  2. 5
    5
      content.go
  3. 71
    27
      context.go
  4. 30
    24
      mux.go
  5. 93
    93
      mux_test.go
  6. 7
    4
      phi.go
  7. 7
    7
      render.go
  8. 2
    2
      tree.go
  9. 28
    28
      tree_test.go

+ 2
- 2
chain.go View File

@@ -25,8 +25,8 @@ type ChainHandler struct {
25 25
 }
26 26
 
27 27
 // Serve the chain.
28
-func (c *ChainHandler) Serve(rctx *Context) {
29
-	c.chain.Serve(rctx)
28
+func (c *ChainHandler) Serve(ctx Context) {
29
+	c.chain.Serve(ctx)
30 30
 }
31 31
 
32 32
 // chain builds a http.Handler composed of an inline middleware stack and endpoint

+ 5
- 5
content.go View File

@@ -8,16 +8,16 @@ import (
8 8
 )
9 9
 
10 10
 // RenderFunc writes content to the context.
11
-type RenderFunc func(ctx *Context, v interface{}) error
11
+type RenderFunc func(ctx Context, v interface{}) error
12 12
 
13 13
 // Render method for the Renderer interface.
14
-func (f RenderFunc) Render(ctx *Context, v interface{}) error {
14
+func (f RenderFunc) Render(ctx Context, v interface{}) error {
15 15
 	return f(ctx, v)
16 16
 }
17 17
 
18 18
 // Renderer implements a content writer.
19 19
 type Renderer interface {
20
-	Render(*Context, interface{}) error
20
+	Render(Context, interface{}) error
21 21
 }
22 22
 
23 23
 // NegotiateContentType returns the best offered content type for the request's
@@ -25,11 +25,11 @@ type Renderer interface {
25 25
 // offer is preferred.  For example, text/* trumps */*. If two offers match
26 26
 // with equal weight and specificity, then the offer earlier in the list is
27 27
 // preferred. If no offers match, then defaultOffer is returned.
28
-func NegotiateContentType(ctx *Context, offers []string, defaultOffer string) string {
28
+func NegotiateContentType(ctx Context, offers []string, defaultOffer string) string {
29 29
 	bestOffer := defaultOffer
30 30
 	bestQ := -1.0
31 31
 	bestWild := 3
32
-	specs := header.ParseAccept(ctx.Request.Header, "Accept")
32
+	specs := header.ParseAccept(ctx.Request().Header, "Accept")
33 33
 	for _, offer := range offers {
34 34
 		for _, spec := range specs {
35 35
 			switch {

+ 71
- 27
context.go View File

@@ -10,13 +10,42 @@ var (
10 10
 	RouteCtxKey = &contextKey{"RouteContext"}
11 11
 )
12 12
 
13
-// Context is the default routing context set on the root node of a
14
-// request context to track URL parameters and an optional routing path.
15
-type Context struct {
13
+// Context is the generic context interface.
14
+type Context interface {
16 15
 	http.ResponseWriter
17 16
 
18
-	// Request is the original http.Request.
19
-	Request *http.Request
17
+	// Request is the orignal HTTP request.
18
+	Request() *http.Request
19
+
20
+	// Context cancellation.
21
+	Done() <-chan struct{}
22
+
23
+	// Error response.
24
+	Error(err error, status ...int)
25
+
26
+	// Redirect response.
27
+	Redirect(location string, status ...int)
28
+
29
+	// Param retrieves a named URL parameter.
30
+	Param(key string) string
31
+
32
+	// Data defined by the user.
33
+	Data() map[string]interface{}
34
+
35
+	// SetData defined by the user.
36
+	SetData(key string, value interface{})
37
+
38
+	// Value from the request context.
39
+	Value(key interface{}) interface{}
40
+
41
+	// SetValue in the request context.
42
+	SetValue(key, value interface{})
43
+}
44
+
45
+// RoutingContext is the default routing context set on the root node of a
46
+// request context to track URL parameters and an optional routing path.
47
+type RoutingContext struct {
48
+	http.ResponseWriter
20 49
 
21 50
 	// URL routing parameter key and values.
22 51
 	URLParams params
@@ -32,30 +61,45 @@ type Context struct {
32 61
 	RoutePatterns []string
33 62
 
34 63
 	// Data set by the user.
35
-	Data map[string]interface{}
64
+	data map[string]interface{}
65
+
66
+	// Request is the original http.Request.
67
+	request *http.Request
36 68
 }
37 69
 
38
-// NewRouteContext returns a new routing Context object.
39
-func NewRouteContext() *Context {
40
-	return &Context{
41
-		Data: make(map[string]interface{}),
70
+// NewRoutingContext returns a new RoutingContext.
71
+func NewRoutingContext() *RoutingContext {
72
+	return &RoutingContext{
73
+		data: make(map[string]interface{}),
42 74
 	}
43 75
 }
44 76
 
45 77
 // reset a routing context to its initial state.
46
-func (x *Context) reset(w http.ResponseWriter, r *http.Request) {
78
+func (x *RoutingContext) reset(w http.ResponseWriter, r *http.Request) {
47 79
 	r = r.WithContext(context.WithValue(r.Context(), RouteCtxKey, x))
48 80
 	x.ResponseWriter = w
49
-	x.Request = r
81
+	x.request = r
50 82
 	x.URLParams = x.URLParams[:0]
51 83
 	x.RoutePath = ""
52 84
 	x.RoutePattern = ""
53 85
 	x.RoutePatterns = x.RoutePatterns[:0]
54
-	x.Data = make(map[string]interface{})
86
+	x.data = make(map[string]interface{})
87
+}
88
+
89
+func (x *RoutingContext) Request() *http.Request {
90
+	return x.request
91
+}
92
+
93
+func (x *RoutingContext) Data() map[string]interface{} {
94
+	return x.data
95
+}
96
+
97
+func (x *RoutingContext) SetData(key string, value interface{}) {
98
+	x.data[key] = value
55 99
 }
56 100
 
57 101
 // Error renders a default error page.
58
-func (x *Context) Error(err error, status ...int) {
102
+func (x *RoutingContext) Error(err error, status ...int) {
59 103
 	code := http.StatusInternalServerError
60 104
 	if len(status) == 1 {
61 105
 		code = status[0]
@@ -73,40 +117,40 @@ func (x *Context) Error(err error, status ...int) {
73 117
 }
74 118
 
75 119
 // Redirect to a new location
76
-func (x *Context) Redirect(location string, status ...int) {
120
+func (x *RoutingContext) Redirect(location string, status ...int) {
77 121
 	code := http.StatusFound
78 122
 	if len(status) == 1 {
79 123
 		code = status[0]
80 124
 	}
81
-	http.Redirect(x, x.Request, location, code)
125
+	http.Redirect(x, x.request, location, code)
82 126
 }
83 127
 
84 128
 // Param retrieves a named URL parameter.
85
-func (x *Context) Param(key string) string {
129
+func (x *RoutingContext) Param(key string) string {
86 130
 	return x.URLParams.Get(key)
87 131
 }
88 132
 
89 133
 /* Wrappers for http.Request.Context and friends */
90 134
 
91 135
 // Done channel for cancelation.
92
-func (x *Context) Done() <-chan struct{} {
93
-	return x.Request.Context().Done()
136
+func (x *RoutingContext) Done() <-chan struct{} {
137
+	return x.request.Context().Done()
94 138
 }
95 139
 
96 140
 // Value retrieves a value from http.Request context.
97
-func (x *Context) Value(key interface{}) interface{} {
98
-	return x.Request.Context().Value(key)
141
+func (x *RoutingContext) Value(key interface{}) interface{} {
142
+	return x.request.Context().Value(key)
99 143
 }
100 144
 
101 145
 // SetValue adds a key-value pair to the http.Request context.
102
-func (x *Context) SetValue(key, value interface{}) {
103
-	x.Request = x.Request.WithContext(context.WithValue(x.Request.Context(), key, value))
146
+func (x *RoutingContext) SetValue(key, value interface{}) {
147
+	x.request = x.request.WithContext(context.WithValue(x.request.Context(), key, value))
104 148
 }
105 149
 
106
-// RouteContext returns chi's routing Context object from a
150
+// RouteContext returns phi's routing Context object from a
107 151
 // http.Request Context.
108
-func RouteContext(ctx context.Context) *Context {
109
-	return ctx.Value(RouteCtxKey).(*Context)
152
+func RouteContext(ctx context.Context) Context {
153
+	return ctx.Value(RouteCtxKey).(Context)
110 154
 }
111 155
 
112 156
 // URLParam returns the url parameter from a http.Request object.
@@ -122,7 +166,7 @@ func URLParam(r *http.Request, key string) string {
122 166
 // URLParam returns the url parameter from a http.Request Context.
123 167
 func URLParamFromCtx(ctx context.Context, key string) string {
124 168
 	if rctx := RouteContext(ctx); rctx != nil {
125
-		return rctx.URLParams.Get(key)
169
+		return rctx.Param(key)
126 170
 	}
127 171
 	return ""
128 172
 }

+ 30
- 24
mux.go View File

@@ -44,13 +44,13 @@ type Mux struct {
44 44
 func NewMux() *Mux {
45 45
 	mux := &Mux{tree: &node{}}
46 46
 	mux.pool.New = func() interface{} {
47
-		return NewRouteContext()
47
+		return NewRoutingContext()
48 48
 	}
49 49
 	return mux
50 50
 }
51 51
 
52 52
 // Serve is the single method of the Handler interface.
53
-func (mx *Mux) Serve(ctx *Context) {
53
+func (mx *Mux) Serve(ctx Context) {
54 54
 	// Ensure the mux has some routes defined on the mux
55 55
 	if mx.handler == nil {
56 56
 		panic("phi: attempting to route to a mux with no handlers.")
@@ -69,10 +69,10 @@ func (mx *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
69 69
 	}
70 70
 
71 71
 	// Check if a routing context already exists from a parent router.
72
-	ctx, _ := r.Context().Value(RouteCtxKey).(*Context)
72
+	ctx, _ := r.Context().Value(RouteCtxKey).(*RoutingContext)
73 73
 	if ctx != nil {
74 74
 		ctx.ResponseWriter = w
75
-		ctx.Request = r
75
+		ctx.request = r
76 76
 		mx.Serve(ctx)
77 77
 		return
78 78
 	}
@@ -81,7 +81,7 @@ func (mx *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
81 81
 	// mx.handler that is comprised of mx.middlewares + mx.routeHTTP.
82 82
 	// Once the request is finished, reset the routing context and put it back
83 83
 	// into the pool for reuse from another request.
84
-	ctx = mx.pool.Get().(*Context)
84
+	ctx = mx.pool.Get().(*RoutingContext)
85 85
 	ctx.reset(w, r)
86 86
 	mx.handler.Serve(ctx)
87 87
 	mx.pool.Put(ctx)
@@ -115,13 +115,13 @@ func (mx *Mux) HandleFunc(pattern string, handlerFn HandlerFunc) {
115 115
 // HTTPHandle adds the route `pattern` that matches any http method to
116 116
 // execute the `handler` http.Handler.
117 117
 func (mx *Mux) HTTPHandle(pattern string, handler http.Handler) {
118
-	mx.handle(mALL, pattern, HandlerFunc(func(ctx *Context) { handler.ServeHTTP(ctx, ctx.Request) }))
118
+	mx.handle(mALL, pattern, HandlerFunc(func(ctx Context) { handler.ServeHTTP(ctx, ctx.Request()) }))
119 119
 }
120 120
 
121 121
 // HTTPHandleFunc adds the route `pattern` that matches any http method to
122 122
 // execute the `handlerFn` http.HandlerFunc.
123 123
 func (mx *Mux) HTTPHandleFunc(pattern string, handlerFn http.HandlerFunc) {
124
-	mx.handle(mALL, pattern, HandlerFunc(func(ctx *Context) { handlerFn.ServeHTTP(ctx, ctx.Request) }))
124
+	mx.handle(mALL, pattern, HandlerFunc(func(ctx Context) { handlerFn.ServeHTTP(ctx, ctx.Request()) }))
125 125
 }
126 126
 
127 127
 // Connect adds the route `pattern` that matches a CONNECT http method to
@@ -248,9 +248,10 @@ func (mx *Mux) Mount(pattern string, handler Handler) {
248 248
 	}
249 249
 
250 250
 	// Wrap the sub-router in a handlerFunc to scope the request path for routing.
251
-	subHandler := HandlerFunc(func(ctx *Context) {
252
-		ctx.RoutePath = "/" + ctx.URLParams.Del("*")
253
-		handler.Serve(ctx)
251
+	subHandler := HandlerFunc(func(ctx Context) {
252
+		rctx, _ := ctx.(*RoutingContext)
253
+		rctx.RoutePath = "/" + rctx.URLParams.Del("*")
254
+		handler.Serve(rctx)
254 255
 	})
255 256
 
256 257
 	if pattern == "" || pattern[len(pattern)-1] != '/' {
@@ -291,15 +292,15 @@ func (mx *Mux) FileServer(path string, root http.FileSystem) {
291 292
 	fs := http.StripPrefix(path, http.FileServer(root))
292 293
 
293 294
 	if path != "/" && path[len(path)-1] != '/' {
294
-		mx.Get(path, func(ctx *Context) {
295
+		mx.Get(path, func(ctx Context) {
295 296
 			ctx.Redirect(path+"/", http.StatusMovedPermanently)
296 297
 		})
297 298
 		path += "/"
298 299
 	}
299 300
 	path += "*"
300 301
 
301
-	mx.Get(path, func(ctx *Context) {
302
-		fs.ServeHTTP(ctx, ctx.Request)
302
+	mx.Get(path, func(ctx Context) {
303
+		fs.ServeHTTP(ctx, ctx.Request())
303 304
 	})
304 305
 }
305 306
 
@@ -309,7 +310,7 @@ func (mx *Mux) NotFoundHandler() HandlerFunc {
309 310
 	if mx.notFoundHandler != nil {
310 311
 		return mx.notFoundHandler
311 312
 	}
312
-	return func(ctx *Context) {
313
+	return func(ctx Context) {
313 314
 		ctx.Error(nil, 404)
314 315
 	}
315 316
 }
@@ -349,26 +350,31 @@ func (mx *Mux) handle(method methodTyp, pattern string, handler Handler) *node {
349 350
 
350 351
 // routeContext routes a *Context through the Mux routing tree to serve
351 352
 // the matching handler for a particular http method.
352
-func (mx *Mux) routeContext(ctx *Context) {
353
-	if ctx.Request == nil {
354
-		panic("Context.Request is nil")
353
+func (mx *Mux) routeContext(ctx Context) {
354
+	rctx, _ := ctx.(*RoutingContext)
355
+
356
+	if rctx == nil {
357
+		panic("RoutingContext is nil")
358
+	}
359
+	if rctx.request == nil {
360
+		panic("RoutingContext.request is nil")
355 361
 	}
356 362
 
357 363
 	// The request routing path
358
-	routePath := ctx.RoutePath
364
+	routePath := rctx.RoutePath
359 365
 	if routePath == "" {
360
-		routePath = ctx.Request.URL.Path
366
+		routePath = rctx.request.URL.Path
361 367
 	}
362 368
 
363 369
 	// Check if method is supported by phi
364
-	method, ok := methodMap[ctx.Request.Method]
370
+	method, ok := methodMap[rctx.request.Method]
365 371
 	if !ok {
366
-		methodNotAllowedHandler(ctx)
372
+		methodNotAllowedHandler(rctx)
367 373
 		return
368 374
 	}
369 375
 
370 376
 	// Find the route
371
-	hs := mx.tree.FindRoute(ctx, routePath)
377
+	hs := mx.tree.FindRoute(rctx, routePath)
372 378
 	if hs == nil {
373 379
 		mx.NotFoundHandler().Serve(ctx)
374 380
 		return
@@ -376,7 +382,7 @@ func (mx *Mux) routeContext(ctx *Context) {
376 382
 
377 383
 	h, ok := hs[method]
378 384
 	if !ok {
379
-		methodNotAllowedHandler(ctx)
385
+		methodNotAllowedHandler(rctx)
380 386
 		return
381 387
 	}
382 388
 
@@ -386,7 +392,7 @@ func (mx *Mux) routeContext(ctx *Context) {
386 392
 
387 393
 // methodNotAllowedHandler is a helper function to respond with a 405,
388 394
 // method not allowed.
389
-func methodNotAllowedHandler(ctx *Context) {
395
+func methodNotAllowedHandler(ctx Context) {
390 396
 	ctx.WriteHeader(405)
391 397
 	ctx.Write(nil)
392 398
 }

+ 93
- 93
mux_test.go View File

@@ -18,21 +18,21 @@ import (
18 18
 func TestMuxBasic(t *testing.T) {
19 19
 	var count uint64
20 20
 	countermw := func(next Handler) Handler {
21
-		return HandlerFunc(func(ctx *Context) {
21
+		return HandlerFunc(func(ctx Context) {
22 22
 			count++
23 23
 			next.Serve(ctx)
24 24
 		})
25 25
 	}
26 26
 
27 27
 	usermw := func(next Handler) Handler {
28
-		return HandlerFunc(func(ctx *Context) {
28
+		return HandlerFunc(func(ctx Context) {
29 29
 			ctx.SetValue("user", "peter")
30 30
 			next.Serve(ctx)
31 31
 		})
32 32
 	}
33 33
 
34 34
 	exmw := func(next Handler) Handler {
35
-		return HandlerFunc(func(ctx *Context) {
35
+		return HandlerFunc(func(ctx Context) {
36 36
 			ctx.SetValue("ex", "a")
37 37
 			next.Serve(ctx)
38 38
 		})
@@ -42,59 +42,59 @@ func TestMuxBasic(t *testing.T) {
42 42
 	logbuf := bytes.NewBufferString("")
43 43
 	logmsg := "logmw test"
44 44
 	logmw := func(next Handler) Handler {
45
-		return HandlerFunc(func(ctx *Context) {
45
+		return HandlerFunc(func(ctx Context) {
46 46
 			logbuf.WriteString(logmsg)
47 47
 			next.Serve(ctx)
48 48
 		})
49 49
 	}
50 50
 	_ = logmw
51 51
 
52
-	cxindex := func(ctx *Context) {
52
+	cxindex := func(ctx Context) {
53 53
 		user := ctx.Value("user").(string)
54 54
 		ctx.WriteHeader(200)
55 55
 		ctx.Write([]byte(fmt.Sprintf("hi %s", user)))
56 56
 	}
57 57
 
58
-	ping := func(ctx *Context) {
58
+	ping := func(ctx Context) {
59 59
 		ctx.WriteHeader(200)
60 60
 		ctx.Write([]byte("."))
61 61
 	}
62 62
 
63
-	headPing := func(ctx *Context) {
63
+	headPing := func(ctx Context) {
64 64
 		ctx.Header().Set("X-Ping", "1")
65 65
 		ctx.WriteHeader(200)
66 66
 	}
67 67
 
68
-	createPing := func(ctx *Context) {
68
+	createPing := func(ctx Context) {
69 69
 		// create ....
70 70
 		ctx.WriteHeader(201)
71 71
 	}
72 72
 
73
-	pingAll := func(ctx *Context) {
73
+	pingAll := func(ctx Context) {
74 74
 		ctx.WriteHeader(200)
75 75
 		ctx.Write([]byte("ping all"))
76 76
 	}
77 77
 	_ = pingAll
78 78
 
79
-	pingAll2 := func(ctx *Context) {
79
+	pingAll2 := func(ctx Context) {
80 80
 		ctx.WriteHeader(200)
81 81
 		ctx.Write([]byte("ping all2"))
82 82
 	}
83 83
 	_ = pingAll2
84 84
 
85
-	pingOne := func(ctx *Context) {
85
+	pingOne := func(ctx Context) {
86 86
 		idParam := ctx.Param("id")
87 87
 		ctx.WriteHeader(200)
88 88
 		ctx.Write([]byte(fmt.Sprintf("ping one id: %s", idParam)))
89 89
 	}
90 90
 
91
-	pingWoop := func(ctx *Context) {
91
+	pingWoop := func(ctx Context) {
92 92
 		ctx.WriteHeader(200)
93 93
 		ctx.Write([]byte("woop."))
94 94
 	}
95 95
 	_ = pingWoop
96 96
 
97
-	catchAll := func(ctx *Context) {
97
+	catchAll := func(ctx Context) {
98 98
 		ctx.WriteHeader(200)
99 99
 		ctx.Write([]byte("catchall"))
100 100
 	}
@@ -211,10 +211,10 @@ func TestMuxBasic(t *testing.T) {
211 211
 
212 212
 func TestMuxPlain(t *testing.T) {
213 213
 	r := NewRouter()
214
-	r.Get("/hi", func(ctx *Context) {
214
+	r.Get("/hi", func(ctx Context) {
215 215
 		ctx.Write([]byte("bye"))
216 216
 	})
217
-	r.NotFound(func(ctx *Context) {
217
+	r.NotFound(func(ctx Context) {
218 218
 		ctx.WriteHeader(404)
219 219
 		ctx.Write([]byte("nothing here"))
220 220
 	})
@@ -238,7 +238,7 @@ func TestMuxEmptyRoutes(t *testing.T) {
238 238
 
239 239
 	mux.Handle("/api*", apiRouter)
240 240
 
241
-	if _, body := testHandler(t, mux, "GET", "/", nil); body != "Not Found\n" {
241
+	if _, body := testHandler(t, mux, "GET", "/", nil); body != "Not Found" {
242 242
 		t.Fatalf(body)
243 243
 	}
244 244
 
@@ -273,13 +273,13 @@ func TestMuxEmptyRoutes(t *testing.T) {
273 273
 // for an example of using a middleware to handle trailing slashes.
274 274
 func TestMuxTrailingSlash(t *testing.T) {
275 275
 	r := NewRouter()
276
-	r.NotFound(func(ctx *Context) {
276
+	r.NotFound(func(ctx Context) {
277 277
 		ctx.WriteHeader(404)
278 278
 		ctx.Write([]byte("nothing here"))
279 279
 	})
280 280
 
281 281
 	subRoutes := NewRouter()
282
-	indexHandler := func(ctx *Context) {
282
+	indexHandler := func(ctx Context) {
283 283
 		accountID := ctx.Param("accountID")
284 284
 		ctx.Write([]byte(accountID))
285 285
 	}
@@ -304,25 +304,25 @@ func TestMuxTrailingSlash(t *testing.T) {
304 304
 
305 305
 func TestMuxNestedNotFound(t *testing.T) {
306 306
 	r := NewRouter()
307
-	r.Get("/hi", func(ctx *Context) {
307
+	r.Get("/hi", func(ctx Context) {
308 308
 		ctx.Write([]byte("bye"))
309 309
 	})
310
-	r.NotFound(func(ctx *Context) {
310
+	r.NotFound(func(ctx Context) {
311 311
 		ctx.WriteHeader(404)
312 312
 		ctx.Write([]byte("root 404"))
313 313
 	})
314 314
 
315 315
 	sr1 := NewRouter()
316
-	sr1.Get("/sub", func(ctx *Context) {
316
+	sr1.Get("/sub", func(ctx Context) {
317 317
 		ctx.Write([]byte("sub"))
318 318
 	})
319
-	sr1.NotFound(func(ctx *Context) {
319
+	sr1.NotFound(func(ctx Context) {
320 320
 		ctx.WriteHeader(404)
321 321
 		ctx.Write([]byte("sub 404"))
322 322
 	})
323 323
 
324 324
 	sr2 := NewRouter()
325
-	sr2.Get("/sub", func(ctx *Context) {
325
+	sr2.Get("/sub", func(ctx Context) {
326 326
 		ctx.Write([]byte("sub2"))
327 327
 	})
328 328
 
@@ -359,7 +359,7 @@ func TestMuxWith(t *testing.T) {
359 359
 	var cmwInit2, cmwHandler2 uint64
360 360
 	mw1 := func(next Handler) Handler {
361 361
 		cmwInit1++
362
-		return HandlerFunc(func(ctx *Context) {
362
+		return HandlerFunc(func(ctx Context) {
363 363
 			cmwHandler1++
364 364
 			ctx.SetValue("inline1", "yes")
365 365
 			next.Serve(ctx)
@@ -367,7 +367,7 @@ func TestMuxWith(t *testing.T) {
367 367
 	}
368 368
 	mw2 := func(next Handler) Handler {
369 369
 		cmwInit2++
370
-		return HandlerFunc(func(ctx *Context) {
370
+		return HandlerFunc(func(ctx Context) {
371 371
 			cmwHandler2++
372 372
 			ctx.SetValue("inline2", "yes")
373 373
 			next.Serve(ctx)
@@ -375,10 +375,10 @@ func TestMuxWith(t *testing.T) {
375 375
 	}
376 376
 
377 377
 	r := NewRouter()
378
-	r.Get("/hi", func(ctx *Context) {
378
+	r.Get("/hi", func(ctx Context) {
379 379
 		ctx.Write([]byte("bye"))
380 380
 	})
381
-	r.With(mw1).With(mw2).Get("/inline", func(ctx *Context) {
381
+	r.With(mw1).With(mw2).Get("/inline", func(ctx Context) {
382 382
 		v1 := ctx.Value("inline1").(string)
383 383
 		v2 := ctx.Value("inline2").(string)
384 384
 		ctx.Write([]byte(fmt.Sprintf("inline %s %s", v1, v2)))
@@ -411,7 +411,7 @@ func TestMuxMiddlewareStack(t *testing.T) {
411 411
 	var stdmwInit, stdmwHandler uint64
412 412
 	stdmw := func(next Handler) Handler {
413 413
 		stdmwInit++
414
-		return HandlerFunc(func(ctx *Context) {
414
+		return HandlerFunc(func(ctx Context) {
415 415
 			stdmwHandler++
416 416
 			next.Serve(ctx)
417 417
 		})
@@ -421,7 +421,7 @@ func TestMuxMiddlewareStack(t *testing.T) {
421 421
 	var ctxmwInit, ctxmwHandler uint64
422 422
 	ctxmw := func(next Handler) Handler {
423 423
 		ctxmwInit++
424
-		return HandlerFunc(func(ctx *Context) {
424
+		return HandlerFunc(func(ctx Context) {
425 425
 			ctxmwHandler++
426 426
 			ctx.SetValue("count.ctxmwHandler", ctxmwHandler)
427 427
 			next.Serve(ctx)
@@ -431,7 +431,7 @@ func TestMuxMiddlewareStack(t *testing.T) {
431 431
 	var inCtxmwInit, inCtxmwHandler uint64
432 432
 	inCtxmw := func(next Handler) Handler {
433 433
 		inCtxmwInit++
434
-		return HandlerFunc(func(ctx *Context) {
434
+		return HandlerFunc(func(ctx Context) {
435 435
 			inCtxmwHandler++
436 436
 			next.Serve(ctx)
437 437
 		})
@@ -441,8 +441,8 @@ func TestMuxMiddlewareStack(t *testing.T) {
441 441
 	r.Use(stdmw)
442 442
 	r.Use(ctxmw)
443 443
 	r.Use(func(next Handler) Handler {
444
-		return HandlerFunc(func(ctx *Context) {
445
-			if ctx.Request.URL.Path == "/ping" {
444
+		return HandlerFunc(func(ctx Context) {
445
+			if ctx.Request().URL.Path == "/ping" {
446 446
 				ctx.Write([]byte("pong"))
447 447
 				return
448 448
 			}
@@ -452,13 +452,13 @@ func TestMuxMiddlewareStack(t *testing.T) {
452 452
 
453 453
 	var handlerCount uint64
454 454
 
455
-	r.With(inCtxmw).Get("/", func(ctx *Context) {
455
+	r.With(inCtxmw).Get("/", func(ctx Context) {
456 456
 		handlerCount++
457 457
 		ctxmwHandlerCount := ctx.Value("count.ctxmwHandler").(uint64)
458 458
 		ctx.Write([]byte(fmt.Sprintf("inits:%d reqs:%d ctxValue:%d", ctxmwInit, handlerCount, ctxmwHandlerCount)))
459 459
 	})
460 460
 
461
-	r.Get("/hi", func(ctx *Context) {
461
+	r.Get("/hi", func(ctx Context) {
462 462
 		ctx.Write([]byte("wooot"))
463 463
 	})
464 464
 
@@ -484,7 +484,7 @@ func TestMuxRouteGroups(t *testing.T) {
484 484
 
485 485
 	stdmw := func(next Handler) Handler {
486 486
 		stdmwInit++
487
-		return HandlerFunc(func(ctx *Context) {
487
+		return HandlerFunc(func(ctx Context) {
488 488
 			stdmwHandler++
489 489
 			next.Serve(ctx)
490 490
 		})
@@ -493,7 +493,7 @@ func TestMuxRouteGroups(t *testing.T) {
493 493
 	var stdmwInit2, stdmwHandler2 uint64
494 494
 	stdmw2 := func(next Handler) Handler {
495 495
 		stdmwInit2++
496
-		return HandlerFunc(func(ctx *Context) {
496
+		return HandlerFunc(func(ctx Context) {
497 497
 			stdmwHandler2++
498 498
 			next.Serve(ctx)
499 499
 		})
@@ -502,13 +502,13 @@ func TestMuxRouteGroups(t *testing.T) {
502 502
 	r := NewRouter()
503 503
 	r.Group(func(r Router) {
504 504
 		r.Use(stdmw)
505
-		r.Get("/group", func(ctx *Context) {
505
+		r.Get("/group", func(ctx Context) {
506 506
 			ctx.Write([]byte("root group"))
507 507
 		})
508 508
 	})
509 509
 	r.Group(func(r Router) {
510 510
 		r.Use(stdmw2)
511
-		r.Get("/group2", func(ctx *Context) {
511
+		r.Get("/group2", func(ctx Context) {
512 512
 			ctx.Write([]byte("root group2"))
513 513
 		})
514 514
 	})
@@ -540,32 +540,32 @@ func TestMuxBig(t *testing.T) {
540 540
 	var r, sr1, sr2, sr3, sr4, sr5, sr6 *Mux
541 541
 	r = NewRouter()
542 542
 	r.Use(func(next Handler) Handler {
543
-		return HandlerFunc(func(ctx *Context) {
543
+		return HandlerFunc(func(ctx Context) {
544 544
 			ctx.SetValue("requestID", "1")
545 545
 			next.Serve(ctx)
546 546
 		})
547 547
 	})
548 548
 	r.Use(func(next Handler) Handler {
549
-		return HandlerFunc(func(ctx *Context) {
549
+		return HandlerFunc(func(ctx Context) {
550 550
 			next.Serve(ctx)
551 551
 		})
552 552
 	})
553 553
 	r.Group(func(r Router) {
554 554
 		r.Use(func(next Handler) Handler {
555
-			return HandlerFunc(func(ctx *Context) {
555
+			return HandlerFunc(func(ctx Context) {
556 556
 				ctx.SetValue("session.user", "anonymous")
557 557
 				next.Serve(ctx)
558 558
 			})
559 559
 		})
560
-		r.Get("/favicon.ico", func(ctx *Context) {
560
+		r.Get("/favicon.ico", func(ctx Context) {
561 561
 			ctx.Write([]byte("fav"))
562 562
 		})
563
-		r.Get("/hubs/:hubID/view", func(ctx *Context) {
563
+		r.Get("/hubs/:hubID/view", func(ctx Context) {
564 564
 			s := fmt.Sprintf("/hubs/%s/view reqid:%s session:%s", ctx.Param("hubID"),
565 565
 				ctx.Value("requestID"), ctx.Value("session.user"))
566 566
 			ctx.Write([]byte(s))
567 567
 		})
568
-		r.Get("/hubs/:hubID/view/*", func(ctx *Context) {
568
+		r.Get("/hubs/:hubID/view/*", func(ctx Context) {
569 569
 			s := fmt.Sprintf("/hubs/%s/view/%s reqid:%s session:%s", ctx.Param("hubID"),
570 570
 				ctx.Param("*"), ctx.Value("requestID"), ctx.Value("session.user"))
571 571
 			ctx.Write([]byte(s))
@@ -573,21 +573,21 @@ func TestMuxBig(t *testing.T) {
573 573
 	})
574 574
 	r.Group(func(r Router) {
575 575
 		r.Use(func(next Handler) Handler {
576
-			return HandlerFunc(func(ctx *Context) {
576
+			return HandlerFunc(func(ctx Context) {
577 577
 				ctx.SetValue("session.user", "elvis")
578 578
 				next.Serve(ctx)
579 579
 			})
580 580
 		})
581
-		r.Get("/", func(ctx *Context) {
581
+		r.Get("/", func(ctx Context) {
582 582
 			s := fmt.Sprintf("/ reqid:%s session:%s", ctx.Value("requestID"), ctx.Value("session.user"))
583 583
 			ctx.Write([]byte(s))
584 584
 		})
585
-		r.Get("/suggestions", func(ctx *Context) {
585
+		r.Get("/suggestions", func(ctx Context) {
586 586
 			s := fmt.Sprintf("/suggestions reqid:%s session:%s", ctx.Value("requestID"), ctx.Value("session.user"))
587 587
 			ctx.Write([]byte(s))
588 588
 		})
589 589
 
590
-		r.Get("/woot/:wootID/*", func(ctx *Context) {
590
+		r.Get("/woot/:wootID/*", func(ctx Context) {
591 591
 			s := fmt.Sprintf("/woot/%s/%s", ctx.Param("wootID"), ctx.Param("*"))
592 592
 			ctx.Write([]byte(s))
593 593
 		})
@@ -596,26 +596,26 @@ func TestMuxBig(t *testing.T) {
596 596
 			sr1 = r.(*Mux)
597 597
 			r.Route("/:hubID", func(r Router) {
598 598
 				sr2 = r.(*Mux)
599
-				r.Get("/", func(ctx *Context) {
599
+				r.Get("/", func(ctx Context) {
600 600
 					s := fmt.Sprintf("/hubs/%s reqid:%s session:%s",
601 601
 						ctx.Param("hubID"), ctx.Value("requestID"), ctx.Value("session.user"))
602 602
 					ctx.Write([]byte(s))
603 603
 				})
604
-				r.Get("/touch", func(ctx *Context) {
604
+				r.Get("/touch", func(ctx Context) {
605 605
 					s := fmt.Sprintf("/hubs/%s/touch reqid:%s session:%s", ctx.Param("hubID"),
606 606
 						ctx.Value("requestID"), ctx.Value("session.user"))
607 607
 					ctx.Write([]byte(s))
608 608
 				})
609 609
 
610 610
 				sr3 = NewRouter()
611
-				sr3.Get("/", func(ctx *Context) {
611
+				sr3.Get("/", func(ctx Context) {
612 612
 					s := fmt.Sprintf("/hubs/%s/webhooks reqid:%s session:%s", ctx.Param("hubID"),
613 613
 						ctx.Value("requestID"), ctx.Value("session.user"))
614 614
 					ctx.Write([]byte(s))
615 615
 				})
616 616
 				sr3.Route("/:webhookID", func(r Router) {
617 617
 					sr4 = r.(*Mux)
618
-					r.Get("/", func(ctx *Context) {
618
+					r.Get("/", func(ctx Context) {
619 619
 						s := fmt.Sprintf("/hubs/%s/webhooks/%s reqid:%s session:%s", ctx.Param("hubID"),
620 620
 							ctx.Param("webhookID"), ctx.Value("requestID"), ctx.Value("session.user"))
621 621
 						ctx.Write([]byte(s))
@@ -627,7 +627,7 @@ func TestMuxBig(t *testing.T) {
627 627
 				// perhaps add .Router() to the middleware inline thing..
628 628
 				// and use that always.. or, can detect in that method..
629 629
 				r.Mount("/webhooks", Chain(func(next Handler) Handler {
630
-					return HandlerFunc(func(ctx *Context) {
630
+					return HandlerFunc(func(ctx Context) {
631 631
 						ctx.SetValue("hook", true)
632 632
 						next.Serve(ctx)
633 633
 					})
@@ -643,7 +643,7 @@ func TestMuxBig(t *testing.T) {
643 643
 
644 644
 				r.Route("/posts", func(r Router) {
645 645
 					sr5 = r.(*Mux)
646
-					r.Get("/", func(ctx *Context) {
646
+					r.Get("/", func(ctx Context) {
647 647
 						s := fmt.Sprintf("/hubs/%s/posts reqid:%s session:%s", ctx.Param("hubID"),
648 648
 							ctx.Value("requestID"), ctx.Value("session.user"))
649 649
 						ctx.Write([]byte(s))
@@ -654,12 +654,12 @@ func TestMuxBig(t *testing.T) {
654 654
 
655 655
 		r.Route("/folders/", func(r Router) {
656 656
 			sr6 = r.(*Mux)
657
-			r.Get("/", func(ctx *Context) {
657
+			r.Get("/", func(ctx Context) {
658 658
 				s := fmt.Sprintf("/folders/ reqid:%s session:%s",
659 659
 					ctx.Value("requestID"), ctx.Value("session.user"))
660 660
 				ctx.Write([]byte(s))
661 661
 			})
662
-			r.Get("/public", func(ctx *Context) {
662
+			r.Get("/public", func(ctx Context) {
663 663
 				s := fmt.Sprintf("/folders/public reqid:%s session:%s",
664 664
 					ctx.Value("requestID"), ctx.Value("session.user"))
665 665
 				ctx.Write([]byte(s))
@@ -699,7 +699,7 @@ func TestMuxBig(t *testing.T) {
699 699
 	_, body = testRequest(t, ts, "GET", "/hubs/123", nil)
700 700
 	expected = "/hubs/123 reqid:1 session:elvis"
701 701
 	if body != expected {
702
-		t.Fatalf("expected:%s got:%s", expected, body)
702
+		t.Fatalf("expected:%q got:%q", expected, body)
703 703
 	}
704 704
 	_, body = testRequest(t, ts, "GET", "/hubs/123/touch", nil)
705 705
 	if body != "/hubs/123/touch reqid:1 session:elvis" {
@@ -714,7 +714,7 @@ func TestMuxBig(t *testing.T) {
714 714
 		t.Fatalf("got '%s'", body)
715 715
 	}
716 716
 	_, body = testRequest(t, ts, "GET", "/folders", nil)
717
-	if body != "Not Found\n" {
717
+	if body != "Not Found" {
718 718
 		t.Fatalf("got '%s'", body)
719 719
 	}
720 720
 	_, body = testRequest(t, ts, "GET", "/folders/", nil)
@@ -726,25 +726,25 @@ func TestMuxBig(t *testing.T) {
726 726
 		t.Fatalf("got '%s'", body)
727 727
 	}
728 728
 	_, body = testRequest(t, ts, "GET", "/folders/nothing", nil)
729
-	if body != "Not Found\n" {
729
+	if body != "Not Found" {
730 730
 		t.Fatalf("got '%s'", body)
731 731
 	}
732 732
 }
733 733
 
734 734
 func TestMuxSubroutes(t *testing.T) {
735
-	hHubView1 := HandlerFunc(func(ctx *Context) {
735
+	hHubView1 := HandlerFunc(func(ctx Context) {
736 736
 		ctx.Write([]byte("hub1"))
737 737
 	})
738
-	hHubView2 := HandlerFunc(func(ctx *Context) {
738
+	hHubView2 := HandlerFunc(func(ctx Context) {
739 739
 		ctx.Write([]byte("hub2"))
740 740
 	})
741
-	hHubView3 := HandlerFunc(func(ctx *Context) {
741
+	hHubView3 := HandlerFunc(func(ctx Context) {
742 742
 		ctx.Write([]byte("hub3"))
743 743
 	})
744
-	hAccountView1 := HandlerFunc(func(ctx *Context) {
744
+	hAccountView1 := HandlerFunc(func(ctx Context) {
745 745
 		ctx.Write([]byte("account1"))
746 746
 	})
747
-	hAccountView2 := HandlerFunc(func(ctx *Context) {
747
+	hAccountView2 := HandlerFunc(func(ctx Context) {
748 748
 		ctx.Write([]byte("account2"))
749 749
 	})
750 750
 
@@ -780,39 +780,39 @@ func TestMuxSubroutes(t *testing.T) {
780 780
 	_, body = testRequest(t, ts, "GET", "/hubs/123/view", nil)
781 781
 	expected = "hub1"
782 782
 	if body != expected {
783
-		t.Fatalf("expected:%s got:%s", expected, body)
783
+		t.Fatalf("expected:%q got:%q", expected, body)
784 784
 	}
785 785
 	_, body = testRequest(t, ts, "GET", "/hubs/123/view/index.html", nil)
786 786
 	expected = "hub2"
787 787
 	if body != expected {
788
-		t.Fatalf("expected:%s got:%s", expected, body)
788
+		t.Fatalf("expected:%q got:%q", expected, body)
789 789
 	}
790 790
 	_, body = testRequest(t, ts, "GET", "/hubs/123/users", nil)
791 791
 	expected = "hub3"
792 792
 	if body != expected {
793
-		t.Fatalf("expected:%s got:%s", expected, body)
793
+		t.Fatalf("expected:%q got:%q", expected, body)
794 794
 	}
795 795
 	resp, body = testRequest(t, ts, "GET", "/hubs/123/users/", nil)
796
-	expected = "Not Found\n"
796
+	expected = "Not Found"
797 797
 	if resp.StatusCode != 404 || body != expected {
798
-		t.Fatalf("expected:%s got:%s", expected, body)
798
+		t.Fatalf("expected:%q got:%q", expected, body)
799 799
 	}
800 800
 	_, body = testRequest(t, ts, "GET", "/accounts/44", nil)
801 801
 	expected = "account1"
802 802
 	if body != expected {
803
-		t.Fatalf("request:%s expected:%s got:%s", "GET /accounts/44", expected, body)
803
+		t.Fatalf("request:%s expected:%q got:%q", "GET /accounts/44", expected, body)
804 804
 	}
805 805
 	_, body = testRequest(t, ts, "GET", "/accounts/44/hi", nil)
806 806
 	expected = "account2"
807 807
 	if body != expected {
808
-		t.Fatalf("expected:%s got:%s", expected, body)
808
+		t.Fatalf("expected:%q got:%q", expected, body)
809 809
 	}
810 810
 
811 811
 	// Test that we're building the routingPatterns properly
812 812
 	router := r
813 813
 	req, _ := http.NewRequest("GET", "/accounts/44/hi", nil)
814 814
 
815
-	ctx := NewRouteContext()
815
+	ctx := NewRoutingContext()
816 816
 	req = req.WithContext(context.WithValue(req.Context(), RouteCtxKey, ctx))
817 817
 
818 818
 	w := httptest.NewRecorder()
@@ -821,7 +821,7 @@ func TestMuxSubroutes(t *testing.T) {
821 821
 	body = string(w.Body.Bytes())
822 822
 	expected = "account2"
823 823
 	if body != expected {
824
-		t.Fatalf("expected:%s got:%s", expected, body)
824
+		t.Fatalf("expected:%q got:%q", expected, body)
825 825
 	}
826 826
 
827 827
 	routePatterns := ctx.RoutePatterns
@@ -830,27 +830,27 @@ func TestMuxSubroutes(t *testing.T) {
830 830
 	}
831 831
 	expected = "/accounts/:accountID/*"
832 832
 	if routePatterns[0] != expected {
833
-		t.Fatalf("routePattern, expected:%s got:%s", expected, routePatterns[0])
833
+		t.Fatalf("routePattern, expected:%q got:%q", expected, routePatterns[0])
834 834
 	}
835 835
 	expected = "/*"
836 836
 	if routePatterns[1] != expected {
837
-		t.Fatalf("routePattern, expected:%s got:%s", expected, routePatterns[1])
837
+		t.Fatalf("routePattern, expected:%q got:%q", expected, routePatterns[1])
838 838
 	}
839 839
 	expected = "/hi"
840 840
 	if routePatterns[2] != expected {
841
-		t.Fatalf("routePattern, expected:%s got:%s", expected, routePatterns[2])
841
+		t.Fatalf("routePattern, expected:%q got:%q", expected, routePatterns[2])
842 842
 	}
843 843
 
844 844
 }
845 845
 
846 846
 func TestSingleHandler(t *testing.T) {
847
-	h := HandlerFunc(func(ctx *Context) {
847
+	h := HandlerFunc(func(ctx Context) {
848 848
 		name := ctx.Param("name")
849 849
 		ctx.Write([]byte("hi " + name))
850 850
 	})
851 851
 
852 852
 	r, _ := http.NewRequest("GET", "/", nil)
853
-	ctx := NewRouteContext()
853
+	ctx := NewRoutingContext()
854 854
 	r = r.WithContext(context.WithValue(r.Context(), RouteCtxKey, ctx))
855 855
 
856 856
 	w := httptest.NewRecorder()
@@ -863,7 +863,7 @@ func TestSingleHandler(t *testing.T) {
863 863
 	body := string(w.Body.Bytes())
864 864
 	expected := "hi joe"
865 865
 	if body != expected {
866
-		t.Fatalf("expected:%s got:%s", expected, body)
866
+		t.Fatalf("expected:%q got:%q", expected, body)
867 867
 	}
868 868
 }
869 869
 
@@ -883,7 +883,7 @@ func TestSingleHandler(t *testing.T) {
883 883
 // 	var r Router = NewRouter()
884 884
 //
885 885
 // 	var r2 Router = NewACLMux() //NewRouter()
886
-// 	r2.Get("/hi", func(ctx *Context) {
886
+// 	r2.Get("/hi", func(ctx Context) {
887 887
 // 		ctx.Write([]byte("hi"))
888 888
 // 	})
889 889
 //
@@ -892,11 +892,11 @@ func TestSingleHandler(t *testing.T) {
892 892
 
893 893
 func TestServeHTTPExistingContext(t *testing.T) {
894 894
 	r := NewRouter()
895
-	r.Get("/hi", func(ctx *Context) {
895
+	r.Get("/hi", func(ctx Context) {
896 896
 		s, _ := ctx.Value("testCtx").(string)
897 897
 		ctx.Write([]byte(s))
898 898
 	})
899
-	r.NotFound(func(ctx *Context) {
899
+	r.NotFound(func(ctx Context) {
900 900
 		s, _ := ctx.Value("testCtx").(string)
901 901
 		ctx.WriteHeader(404)
902 902
 		ctx.Write([]byte(s))
@@ -947,13 +947,13 @@ func TestServeHTTPExistingContext(t *testing.T) {
947 947
 }
948 948
 
949 949
 func TestNestedGroups(t *testing.T) {
950
-	handlerPrintCounter := func(ctx *Context) {
950
+	handlerPrintCounter := func(ctx Context) {
951 951
 		counter, _ := ctx.Value("counter").(int)
952 952
 		ctx.Write([]byte(fmt.Sprintf("%v", counter)))
953 953
 	}
954 954
 
955 955
 	mwIncreaseCounter := func(next Handler) Handler {
956
-		return HandlerFunc(func(ctx *Context) {
956
+		return HandlerFunc(func(ctx Context) {
957 957
 			counter, _ := ctx.Value("counter").(int)
958 958
 			counter++
959 959
 			ctx.SetValue("counter", counter)
@@ -1002,12 +1002,12 @@ func TestNestedGroups(t *testing.T) {
1002 1002
 }
1003 1003
 
1004 1004
 func TestMiddlewarePanicOnLateUse(t *testing.T) {
1005
-	handler := func(ctx *Context) {
1005
+	handler := func(ctx Context) {
1006 1006
 		ctx.Write([]byte("hello\n"))
1007 1007
 	}
1008 1008
 
1009 1009
 	mw := func(next Handler) Handler {
1010
-		return HandlerFunc(func(ctx *Context) {
1010
+		return HandlerFunc(func(ctx Context) {
1011 1011
 			next.Serve(ctx)
1012 1012
 		})
1013 1013
 	}
@@ -1024,7 +1024,7 @@ func TestMiddlewarePanicOnLateUse(t *testing.T) {
1024 1024
 }
1025 1025
 
1026 1026
 func TestMountingExistingPath(t *testing.T) {
1027
-	handler := func(ctx *Context) {}
1027
+	handler := func(ctx Context) {}
1028 1028
 
1029 1029
 	defer func() {
1030 1030
 		if recover() == nil {
@@ -1040,8 +1040,8 @@ func TestMountingExistingPath(t *testing.T) {
1040 1040
 
1041 1041
 func TestMuxContextIsThreadSafe(t *testing.T) {
1042 1042
 	router := NewRouter()
1043
-	router.Get("/:id", func(rctx *Context) {
1044
-		ctx, cancel := context.WithTimeout(rctx.Request.Context(), 1*time.Millisecond)
1043
+	router.Get("/:id", func(rctx Context) {
1044
+		ctx, cancel := context.WithTimeout(rctx.Request().Context(), 1*time.Millisecond)
1045 1045
 		defer cancel()
1046 1046
 
1047 1047
 		<-ctx.Done()
@@ -1092,10 +1092,10 @@ func TestMuxFileServer(t *testing.T) {
1092 1092
 
1093 1093
 	r := NewRouter()
1094 1094
 	r.FileServer("/mounted", memfs)
1095
-	r.Get("/hi", func(ctx *Context) {
1095
+	r.Get("/hi", func(ctx Context) {
1096 1096
 		ctx.Write([]byte("bye"))
1097 1097
 	})
1098
-	r.NotFound(func(ctx *Context) {
1098
+	r.NotFound(func(ctx Context) {
1099 1099
 		ctx.WriteHeader(404)
1100 1100
 		ctx.Write([]byte("nothing here"))
1101 1101
 	})
@@ -1152,9 +1152,9 @@ func TestMuxFileServer(t *testing.T) {
1152 1152
 	// }
1153 1153
 }
1154 1154
 
1155
-func urlParams(ctx *Context) map[string]string {
1155
+func urlParams(rctx *RoutingContext) map[string]string {
1156 1156
 	m := make(map[string]string, 0)
1157
-	for _, p := range ctx.URLParams {
1157
+	for _, p := range rctx.URLParams {
1158 1158
 		m[p.Key] = p.Value
1159 1159
 	}
1160 1160
 	return m

+ 7
- 4
phi.go View File

@@ -31,14 +31,17 @@ package phi
31 31
 
32 32
 import "net/http"
33 33
 
34
+// Handler serves phi requests.
34 35
 type Handler interface {
35
-	Serve(*Context)
36
+	Serve(Context)
36 37
 }
37 38
 
38
-type HandlerFunc func(*Context)
39
+// HandlerFunc can handle phi requests.
40
+type HandlerFunc func(Context)
39 41
 
40
-func (f HandlerFunc) Serve(rctx *Context) {
41
-	f(rctx)
42
+// Serve request.
43
+func (f HandlerFunc) Serve(ctx Context) {
44
+	f(ctx)
42 45
 }
43 46
 
44 47
 // NewRouter returns a new Mux object that implements the Router interface.

+ 7
- 7
render.go View File

@@ -16,7 +16,7 @@ var (
16 16
 )
17 17
 
18 18
 // Error returns a HTTP error.
19
-func Error(ctx *Context, v interface{}) {
19
+func Error(ctx Context, v interface{}) {
20 20
 	var (
21 21
 		code = http.StatusInternalServerError
22 22
 		text = http.StatusText(code)
@@ -47,7 +47,7 @@ func Error(ctx *Context, v interface{}) {
47 47
 }
48 48
 
49 49
 // Data returns binary content.
50
-func Data(ctx *Context, v interface{}) error {
50
+func Data(ctx Context, v interface{}) error {
51 51
 	ctx.Header().Set("Content-Type", "application/octet-stream")
52 52
 
53 53
 	var data []byte
@@ -70,7 +70,7 @@ func Data(ctx *Context, v interface{}) error {
70 70
 }
71 71
 
72 72
 // Text returns plain text content.
73
-func Text(ctx *Context, v interface{}) error {
73
+func Text(ctx Context, v interface{}) error {
74 74
 	ctx.Header().Set("Content-Type", "text/plain; charset=utf-8")
75 75
 
76 76
 	var text string
@@ -93,7 +93,7 @@ func Text(ctx *Context, v interface{}) error {
93 93
 }
94 94
 
95 95
 // HTML returns HTML content.
96
-func HTML(ctx *Context, v interface{}) error {
96
+func HTML(ctx Context, v interface{}) error {
97 97
 	ctx.Header().Set("Content-Type", "text/html; charset=utf-8")
98 98
 
99 99
 	var html string
@@ -116,14 +116,14 @@ func HTML(ctx *Context, v interface{}) error {
116 116
 }
117 117
 
118 118
 // JSON returns JSON content.
119
-func JSON(ctx *Context, v interface{}) error {
119
+func JSON(ctx Context, v interface{}) error {
120 120
 	ctx.Header().Set("Content-Type", "application/json; charset=utf-8")
121 121
 	enc := json.NewEncoder(ctx)
122 122
 	return enc.Encode(v)
123 123
 }
124 124
 
125 125
 // XML returns XML content.
126
-func XML(ctx *Context, v interface{}) error {
126
+func XML(ctx Context, v interface{}) error {
127 127
 	ctx.Header().Set("Content-Type", "application/xml; charset=utf-8")
128 128
 	ctx.Write([]byte(xml.Header))
129 129
 	enc := xml.NewEncoder(ctx)
@@ -132,7 +132,7 @@ func XML(ctx *Context, v interface{}) error {
132 132
 }
133 133
 
134 134
 // Negotiated inspects the HTTP Accept header sent by the client and renders a response for the negotiated Content-Type if available.
135
-func Negotiated(ctx *Context, v interface{}, defaultContentType string) error {
135
+func Negotiated(ctx Context, v interface{}, defaultContentType string) error {
136 136
 	driversMutex.RLock()
137 137
 	defer driversMutex.RUnlock()
138 138
 

+ 2
- 2
tree.go View File

@@ -72,7 +72,7 @@ type node struct {
72 72
 	children [ntCatchAll + 1]nodes
73 73
 }
74 74
 
75
-func (n *node) FindRoute(rctx *Context, path string) methodHandlers {
75
+func (n *node) FindRoute(rctx *RoutingContext, path string) methodHandlers {
76 76
 	// Reset the context routing pattern
77 77
 	rctx.RoutePattern = ""
78 78
 
@@ -330,7 +330,7 @@ func (n *node) findEdge(ntyp nodeTyp, label byte) *node {
330 330
 
331 331
 // Recursive edge traversal by checking all nodeTyp groups along the way.
332 332
 // It's like searching through a multi-dimensional radix trie.
333
-func (n *node) findRoute(rctx *Context, path string) *node {
333
+func (n *node) findRoute(rctx *RoutingContext, path string) *node {
334 334
 	nn := n
335 335
 	search := path
336 336
 

+ 28
- 28
tree_test.go View File

@@ -12,27 +12,27 @@ var (
12 12
 )
13 13
 
14 14
 func TestTree(t *testing.T) {
15
-	hStub := HandlerFunc(func(_ *Context) {})
16
-	hIndex := HandlerFunc(func(_ *Context) {})
17
-	hFavicon := HandlerFunc(func(_ *Context) {})
18
-	hArticleList := HandlerFunc(func(_ *Context) {})
19
-	hArticleNear := HandlerFunc(func(_ *Context) {})
20
-	hArticleShow := HandlerFunc(func(_ *Context) {})
21
-	hArticleShowRelated := HandlerFunc(func(_ *Context) {})
22
-	hArticleShowOpts := HandlerFunc(func(_ *Context) {})
23
-	hArticleSlug := HandlerFunc(func(_ *Context) {})
24
-	hArticleByUser := HandlerFunc(func(_ *Context) {})
25
-	hUserList := HandlerFunc(func(_ *Context) {})
26
-	hUserShow := HandlerFunc(func(_ *Context) {})
27
-	hAdminCatchall := HandlerFunc(func(_ *Context) {})
28
-	hAdminAppShow := HandlerFunc(func(_ *Context) {})
29
-	hAdminAppShowCatchall := HandlerFunc(func(_ *Context) {})
30
-	hUserProfile := HandlerFunc(func(_ *Context) {})
31
-	hUserSuper := HandlerFunc(func(_ *Context) {})
32
-	hUserAll := HandlerFunc(func(_ *Context) {})
33
-	hHubView1 := HandlerFunc(func(_ *Context) {})
34
-	hHubView2 := HandlerFunc(func(_ *Context) {})
35
-	hHubView3 := HandlerFunc(func(_ *Context) {})
15
+	hStub := HandlerFunc(func(_ Context) {})
16
+	hIndex := HandlerFunc(func(_ Context) {})
17
+	hFavicon := HandlerFunc(func(_ Context) {})
18
+	hArticleList := HandlerFunc(func(_ Context) {})
19
+	hArticleNear := HandlerFunc(func(_ Context) {})
20
+	hArticleShow := HandlerFunc(func(_ Context) {})
21
+	hArticleShowRelated := HandlerFunc(func(_ Context) {})
22
+	hArticleShowOpts := HandlerFunc(func(_ Context) {})
23
+	hArticleSlug := HandlerFunc(func(_ Context) {})
24
+	hArticleByUser := HandlerFunc(func(_ Context) {})
25
+	hUserList := HandlerFunc(func(_ Context) {})
26
+	hUserShow := HandlerFunc(func(_ Context) {})
27
+	hAdminCatchall := HandlerFunc(func(_ Context) {})
28
+	hAdminAppShow := HandlerFunc(func(_ Context) {})
29
+	hAdminAppShowCatchall := HandlerFunc(func(_ Context) {})
30
+	hUserProfile := HandlerFunc(func(_ Context) {})
31
+	hUserSuper := HandlerFunc(func(_ Context) {})
32
+	hUserAll := HandlerFunc(func(_ Context) {})
33
+	hHubView1 := HandlerFunc(func(_ Context) {})
34
+	hHubView2 := HandlerFunc(func(_ Context) {})
35
+	hHubView3 := HandlerFunc(func(_ Context) {})
36 36
 
37 37
 	tr := &node{}
38 38
 
@@ -139,7 +139,7 @@ func TestTree(t *testing.T) {
139 139
 
140 140
 	for i, tt := range tests {
141 141
 		// params := make(map[string]string, 0)
142
-		rctx := NewRouteContext()
142
+		rctx := NewRoutingContext()
143 143
 
144 144
 		handlers := tr.FindRoute(rctx, tt.r) //, params)
145 145
 		handler, _ := handlers[mGET]
@@ -180,8 +180,8 @@ func debugPrintTree(parent int, i int, n *node, label byte) bool {
180 180
 }
181 181
 
182 182
 func BenchmarkTreeGet(b *testing.B) {
183
-	h1 := HandlerFunc(func(_ *Context) {})
184
-	h2 := HandlerFunc(func(_ *Context) {})
183
+	h1 := HandlerFunc(func(_ Context) {})
184
+	h2 := HandlerFunc(func(_ Context) {})
185 185
 
186 186
 	tr := &node{}
187 187
 	tr.InsertRoute(mGET, "/", h1)
@@ -198,16 +198,16 @@ func BenchmarkTreeGet(b *testing.B) {
198 198
 
199 199
 	for i := 0; i < b.N; i++ {
200 200
 		// params := map[string]string{}
201
-		mctx := NewRouteContext()
201
+		mctx := NewRoutingContext()
202 202
 		tr.FindRoute(mctx, "/ping/123/456")
203 203
 		// tr.Find("/pingggg", params)
204 204
 	}
205 205
 }
206 206
 
207 207
 // func BenchmarkMuxGet(b *testing.B) {
208
-// 	h1 := HandlerFunc(func(_ *Context) {})
209
-// 	h2 := HandlerFunc(func(_ *Context) {})
210
-// 	h3 := HandlerFunc(func(_ *Context) {})
208
+// 	h1 := HandlerFunc(func(_ Context) {})
209
+// 	h2 := HandlerFunc(func(_ Context) {})
210
+// 	h3 := HandlerFunc(func(_ Context) {})
211 211
 //
212 212
 // 	mx := NewRouter()
213 213
 // 	mx.Get("/", h1)

Loading…
Cancel
Save