Skip to content

Commit 0f8b338

Browse files
author
Olivier Poitrey
committed
Move muxer into its own package
1 parent 0c1c1ee commit 0f8b338

File tree

11 files changed

+141
-90
lines changed

11 files changed

+141
-90
lines changed

README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,28 +73,38 @@ func main() {
7373
}
7474
```
7575

76-
### Using muxer
76+
### Using xmux
7777

78-
Xhandler comes with a context aware muxer forked from [httprouter](https://github.com/julienschmidt/httprouter):
78+
Xhandler comes with an optional context aware muxer forked from [httprouter](https://github.com/julienschmidt/httprouter):
7979

8080
```go
81+
package main
82+
83+
import (
84+
"fmt"
85+
"log"
86+
"net/http"
87+
"time"
88+
89+
"github.com/rs/xhandler"
90+
"github.com/rs/xhandler/xmux"
91+
"golang.org/x/net/context"
92+
)
93+
8194
func main() {
82-
c := xhandler.Chain{}
95+
c := xhandler.Chain{}
8396

8497
// Append a context-aware middleware handler
8598
c.UseC(xhandler.CloseHandler)
8699

87-
// Mix it with a non-context-aware middleware handler
88-
c.Use(cors.Default().Handler)
89-
90100
// Another context-aware middleware handler
91101
c.UseC(xhandler.TimeoutHandler(2 * time.Second))
92102

93-
mux := xhandler.NewMux()
103+
mux := xmux.New()
94104

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

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

xhandler_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
type handler struct{}
1515

16+
type key int
17+
1618
const contextKey key = 0
1719

1820
func newContext(ctx context.Context, value string) context.Context {

mux.go renamed to xmux/mux.go

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
1-
package xhandler
2-
3-
import (
4-
"net/http"
5-
6-
"golang.org/x/net/context"
7-
)
8-
9-
// Mux is a xhandler.HandlerC which can be used to dispatch requests to different
10-
// handler functions via configurable routes
1+
// Package xmux is a net/context aware, tree based high performance HTTP request
2+
// multiplexer forked from httprouter.
3+
//
4+
// A trivial example is:
5+
//
6+
// package main
7+
//
8+
// import (
9+
// "fmt"
10+
// "net/http"
11+
// "log"
12+
//
13+
// "github.com/rs/xhandler"
14+
// "github.com/rs/xhandler/xmux"
15+
// "golang.org/x/net/context"
16+
// )
17+
//
18+
// func Index(ctx context.Context, w http.ResponseWriter, r *http.Request) {
19+
// fmt.Fprint(w, "Welcome!\n")
20+
// }
21+
//
22+
// func Hello(ctx context.Context, w http.ResponseWriter, r *http.Request) {
23+
// fmt.Fprintf(w, "hello, %s!\n", xmux.URLParams(ctx).Get("name"))
24+
// }
25+
//
26+
// func main() {
27+
// mux := xmux.New()
28+
// mux.GET("/", Index)
29+
// mux.GET("/hello/:name", Hello)
30+
//
31+
// log.Fatal(http.ListenAndServe(":8080", xhandler.New(context.Background(), mux)))
32+
// }
1133
//
1234
// The muxer matches incoming requests by the request method and the path.
1335
// If a handle is registered for this path and method, the router delegates the
@@ -45,6 +67,18 @@ import (
4567
// The value of parameters is saved as aParams type saved into the context.
4668
// Parameters can be retrieved by name using xhandler.URLParams(ctx).Get(name) method:
4769
// user := xhandler.URLParams(ctx).Get("user") // defined by :user or *user
70+
package xmux
71+
72+
import (
73+
"net/http"
74+
75+
"github.com/rs/xhandler"
76+
77+
"golang.org/x/net/context"
78+
)
79+
80+
// Mux is a xhandler.HandlerC which can be used to dispatch requests to different
81+
// handler functions via configurable routes
4882
type Mux struct {
4983
trees map[string]*node
5084

@@ -76,12 +110,12 @@ type Mux struct {
76110

77111
// Configurable http.Handler which is called when no matching route is
78112
// found. If it is not set, http.Error with http.StatusNotFound is used.
79-
NotFound HandlerC
113+
NotFound xhandler.HandlerC
80114

81115
// Configurable http.Handler which is called when a request
82116
// cannot be routed and HandleMethodNotAllowed is true.
83117
// If it is not set, http.Error with http.StatusMethodNotAllowed is used.
84-
MethodNotAllowed HandlerC
118+
MethodNotAllowed xhandler.HandlerC
85119

86120
// Function to handle panics recovered from http handlers.
87121
// It should be used to generate a error page and return the http error code
@@ -131,8 +165,8 @@ func URLParams(ctx context.Context) Params {
131165
return emptyParams
132166
}
133167

134-
// NewMux returns a new muxer instance
135-
func NewMux() *Mux {
168+
// New returns a new muxer instance
169+
func New() *Mux {
136170
return &Mux{
137171
RedirectTrailingSlash: true,
138172
RedirectFixedPath: true,
@@ -141,37 +175,37 @@ func NewMux() *Mux {
141175
}
142176

143177
// GET is a shortcut for mux.Handle("GET", path, handler)
144-
func (mux *Mux) GET(path string, handler HandlerC) {
178+
func (mux *Mux) GET(path string, handler xhandler.HandlerC) {
145179
mux.Handle("GET", path, handler)
146180
}
147181

148182
// HEAD is a shortcut for mux.Handle("HEAD", path, handler)
149-
func (mux *Mux) HEAD(path string, handler HandlerC) {
183+
func (mux *Mux) HEAD(path string, handler xhandler.HandlerC) {
150184
mux.Handle("HEAD", path, handler)
151185
}
152186

153187
// OPTIONS is a shortcut for mux.Handle("OPTIONS", path, handler)
154-
func (mux *Mux) OPTIONS(path string, handler HandlerC) {
188+
func (mux *Mux) OPTIONS(path string, handler xhandler.HandlerC) {
155189
mux.Handle("OPTIONS", path, handler)
156190
}
157191

158192
// POST is a shortcut for mux.Handle("POST", path, handler)
159-
func (mux *Mux) POST(path string, handler HandlerC) {
193+
func (mux *Mux) POST(path string, handler xhandler.HandlerC) {
160194
mux.Handle("POST", path, handler)
161195
}
162196

163197
// PUT is a shortcut for mux.Handle("PUT", path, handler)
164-
func (mux *Mux) PUT(path string, handler HandlerC) {
198+
func (mux *Mux) PUT(path string, handler xhandler.HandlerC) {
165199
mux.Handle("PUT", path, handler)
166200
}
167201

168202
// PATCH is a shortcut for mux.Handle("PATCH", path, handler)
169-
func (mux *Mux) PATCH(path string, handler HandlerC) {
203+
func (mux *Mux) PATCH(path string, handler xhandler.HandlerC) {
170204
mux.Handle("PATCH", path, handler)
171205
}
172206

173207
// DELETE is a shortcut for mux.Handle("DELETE", path, handler)
174-
func (mux *Mux) DELETE(path string, handler HandlerC) {
208+
func (mux *Mux) DELETE(path string, handler xhandler.HandlerC) {
175209
mux.Handle("DELETE", path, handler)
176210
}
177211

@@ -183,7 +217,7 @@ func (mux *Mux) DELETE(path string, handler HandlerC) {
183217
// This function is intended for bulk loading and to allow the usage of less
184218
// frequently used, non-standardized or custom methods (e.g. for internal
185219
// communication with a proxy).
186-
func (mux *Mux) Handle(method, path string, handler HandlerC) {
220+
func (mux *Mux) Handle(method, path string, handler xhandler.HandlerC) {
187221
if path[0] != '/' {
188222
panic("path must begin with '/' in path '" + path + "'")
189223
}
@@ -212,7 +246,7 @@ func (mux *Mux) recv(ctx context.Context, w http.ResponseWriter, r *http.Request
212246
// If the path was found, it returns the handle function and the path parameter
213247
// values. Otherwise the third return value indicates whether a redirection to
214248
// the same path with an extra / without the trailing slash should be performed.
215-
func (mux *Mux) Lookup(method, path string) (HandlerC, Params, bool) {
249+
func (mux *Mux) Lookup(method, path string) (xhandler.HandlerC, Params, bool) {
216250
if root := mux.trees[method]; root != nil {
217251
return root.getValue(path)
218252
}

mux_bench_api_test.go renamed to xmux/mux_bench_api_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// Forked from https://github.com/julienschmidt/go-http-routing-benchmark
22
//
3-
package xhandler
3+
package xmux
44

55
import (
66
"net/http"
77
"testing"
88

9+
"github.com/rs/xhandler"
10+
911
"golang.org/x/net/context"
1012
)
1113

@@ -56,21 +58,21 @@ var parseAPI = []route{
5658
}
5759

5860
var (
59-
parseXhandler HandlerC
60-
parseChi HandlerC
61+
parseXhandler xhandler.HandlerC
62+
parseChi xhandler.HandlerC
6163
parseGoji http.Handler
6264
parseHTTPRouter http.Handler
6365
)
6466

65-
func getParseXhandler(b *testing.B) HandlerC {
67+
func getParseXhandler(b *testing.B) xhandler.HandlerC {
6668
defer b.ResetTimer()
6769
if parseXhandler == nil {
6870
parseXhandler = loadXhandler(parseAPI)
6971
}
7072
return parseXhandler
7173
}
7274

73-
func getParseChi(b *testing.B) HandlerC {
75+
func getParseChi(b *testing.B) xhandler.HandlerC {
7476
defer b.ResetTimer()
7577
if parseChi == nil {
7678
parseChi = loadChi(parseAPI)

mux_bench_test.go renamed to xmux/mux_bench_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Forked from https://github.com/julienschmidt/go-http-routing-benchmark
22
//
3-
package xhandler
3+
package xmux
44

55
import (
66
"io"
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/julienschmidt/httprouter"
1212
"github.com/pressly/chi"
13+
"github.com/rs/xhandler"
1314
goji "github.com/zenazn/goji/web"
1415
"golang.org/x/net/context"
1516
)
@@ -21,28 +22,28 @@ type route struct {
2122
path string
2223
}
2324

24-
var httpHandlerC = HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {})
25+
var httpHandlerC = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {})
2526

26-
var xhandlerWrite = HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
27+
var xhandlerWrite = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
2728
io.WriteString(w, URLParams(ctx).Get("name"))
2829
})
2930

30-
func loadXhandler(routes []route) HandlerC {
31+
func loadXhandler(routes []route) xhandler.HandlerC {
3132
h := namedHandler{}
32-
mux := NewMux()
33+
mux := New()
3334
for _, route := range routes {
3435
mux.Handle(route.method, route.path, h)
3536
}
3637
return mux
3738
}
3839

39-
func loadXhandlerSingle(method, path string, h HandlerC) HandlerC {
40-
mux := NewMux()
40+
func loadXhandlerSingle(method, path string, h xhandler.HandlerC) xhandler.HandlerC {
41+
mux := New()
4142
mux.Handle(method, path, h)
4243
return mux
4344
}
4445

45-
func loadChi(routes []route) HandlerC {
46+
func loadChi(routes []route) xhandler.HandlerC {
4647
h := namedHandler{}
4748
router := chi.NewRouter()
4849
for _, route := range routes {
@@ -64,7 +65,7 @@ func loadChi(routes []route) HandlerC {
6465
return router
6566
}
6667

67-
func loadChiSingle(method, path string, h HandlerC) HandlerC {
68+
func loadChiSingle(method, path string, h xhandler.HandlerC) xhandler.HandlerC {
6869
router := chi.NewRouter()
6970
switch method {
7071
case "GET":
@@ -168,7 +169,7 @@ func benchRequest(b *testing.B, router http.Handler, r *http.Request) {
168169
}
169170
}
170171

171-
func benchRequestC(b *testing.B, router HandlerC, ctx context.Context, r *http.Request) {
172+
func benchRequestC(b *testing.B, router xhandler.HandlerC, ctx context.Context, r *http.Request) {
172173
w := new(mockResponseWriter)
173174
u := r.URL
174175
rq := u.RawQuery
@@ -203,7 +204,7 @@ func benchRoutes(b *testing.B, router http.Handler, routes []route) {
203204
}
204205
}
205206

206-
func benchRoutesC(b *testing.B, router HandlerC, ctx context.Context, routes []route) {
207+
func benchRoutesC(b *testing.B, router xhandler.HandlerC, ctx context.Context, routes []route) {
207208
w := new(mockResponseWriter)
208209
r, _ := http.NewRequest("GET", "/", nil)
209210
u := r.URL

mux_example_test.go renamed to xmux/mux_example_test.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
package xhandler_test
1+
package xmux_test
22

33
import (
44
"fmt"
55
"log"
66
"net/http"
77
"time"
88

9-
"github.com/rs/cors"
109
"github.com/rs/xhandler"
10+
"github.com/rs/xhandler/xmux"
1111
"golang.org/x/net/context"
1212
)
1313

@@ -17,17 +17,14 @@ func ExampleMux() {
1717
// Append a context-aware middleware handler
1818
c.UseC(xhandler.CloseHandler)
1919

20-
// Mix it with a non-context-aware middleware handler
21-
c.Use(cors.Default().Handler)
22-
2320
// Another context-aware middleware handler
2421
c.UseC(xhandler.TimeoutHandler(2 * time.Second))
2522

26-
mux := xhandler.NewMux()
23+
mux := xmux.New()
2724

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

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

0 commit comments

Comments
 (0)