Skip to content

Commit dad1702

Browse files
author
Sergio Andrés Virviescas Santana
authored
Merge pull request #9 from AnikHasibul/master
📦 NEW: Router Grouping
2 parents 1dfb16f + d483976 commit dad1702

File tree

2 files changed

+106
-2
lines changed

2 files changed

+106
-2
lines changed

router.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
// func main() {
2828
// r := router.New()
2929
// r.GET("/", Index)
30+
// g := r.Group("/foo", Index)
31+
// g.GET("/bar", Index)
3032
// r.GET("/hello/:name", Hello)
3133

3234
// log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
@@ -89,7 +91,8 @@ var (
8991
// Router is a http.Handler which can be used to dispatch requests to different
9092
// handler functions via configurable routes
9193
type Router struct {
92-
trees map[string]*node
94+
beginPath string
95+
trees map[string]*node
9396

9497
// Enables automatic redirection if the current route can't be matched but a
9598
// handler for the path with (without) the trailing slash exists.
@@ -144,6 +147,19 @@ type Router struct {
144147
// Path auto-correction, including trailing slashes, is enabled by default.
145148
func New() *Router {
146149
return &Router{
150+
beginPath: "/",
151+
RedirectTrailingSlash: true,
152+
RedirectFixedPath: true,
153+
HandleMethodNotAllowed: true,
154+
HandleOPTIONS: true,
155+
}
156+
}
157+
158+
// Group returns a new grouped Router.
159+
// Path auto-correction, including trailing slashes, is enabled by default.
160+
func (r *Router) Group(path string) *Router {
161+
return &Router{
162+
beginPath: path,
147163
RedirectTrailingSlash: true,
148164
RedirectFixedPath: true,
149165
HandleMethodNotAllowed: true,
@@ -198,7 +214,9 @@ func (r *Router) Handle(method, path string, handle fasthttp.RequestHandler) {
198214
if path[0] != '/' {
199215
panic("path must begin with '/' in path '" + path + "'")
200216
}
201-
217+
if r.beginPath != "/" {
218+
path = r.beginPath + path
219+
}
202220
if r.trees == nil {
203221
r.trees = make(map[string]*node)
204222
}

router_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,92 @@ func TestRouterChaining(t *testing.T) {
309309
}
310310
}
311311

312+
func TestRouterGroup(t *testing.T) {
313+
r1 := New()
314+
r2 := r1.Group("/boo")
315+
r1.NotFound = r2.Handler
316+
fooHit := false
317+
r1.POST("/foo", func(ctx *fasthttp.RequestCtx) {
318+
fooHit = true
319+
ctx.SetStatusCode(fasthttp.StatusOK)
320+
})
321+
322+
barHit := false
323+
r2.POST("/bar", func(ctx *fasthttp.RequestCtx) {
324+
barHit = true
325+
ctx.SetStatusCode(fasthttp.StatusOK)
326+
})
327+
328+
s := &fasthttp.Server{
329+
Handler: r1.Handler,
330+
}
331+
332+
rw := &readWriter{}
333+
ch := make(chan error)
334+
335+
rw.r.WriteString("POST /foo HTTP/1.1\r\n\r\n")
336+
go func() {
337+
ch <- s.ServeConn(rw)
338+
}()
339+
select {
340+
case err := <-ch:
341+
if err != nil {
342+
t.Fatalf("return error %s", err)
343+
}
344+
case <-time.After(100 * time.Millisecond):
345+
t.Fatalf("timeout")
346+
}
347+
br := bufio.NewReader(&rw.w)
348+
var resp fasthttp.Response
349+
if err := resp.Read(br); err != nil {
350+
t.Fatalf("Unexpected error when reading response: %s", err)
351+
}
352+
if !(resp.Header.StatusCode() == fasthttp.StatusOK && fooHit) {
353+
t.Errorf("Regular routing failed with router chaining.")
354+
t.FailNow()
355+
}
356+
357+
rw.r.WriteString("POST /boo/bar HTTP/1.1\r\n\r\n")
358+
go func() {
359+
ch <- s.ServeConn(rw)
360+
}()
361+
select {
362+
case err := <-ch:
363+
if err != nil {
364+
t.Fatalf("return error %s", err)
365+
}
366+
case <-time.After(100 * time.Millisecond):
367+
t.Fatalf("timeout")
368+
}
369+
if err := resp.Read(br); err != nil {
370+
t.Fatalf("Unexpected error when reading response: %s", err)
371+
}
372+
if !(resp.Header.StatusCode() == fasthttp.StatusOK && barHit) {
373+
t.Errorf("Chained routing failed with router chaining.")
374+
t.FailNow()
375+
}
376+
377+
rw.r.WriteString("POST /qax HTTP/1.1\r\n\r\n")
378+
go func() {
379+
ch <- s.ServeConn(rw)
380+
}()
381+
select {
382+
case err := <-ch:
383+
if err != nil {
384+
t.Fatalf("return error %s", err)
385+
}
386+
case <-time.After(100 * time.Millisecond):
387+
t.Fatalf("timeout")
388+
}
389+
if err := resp.Read(br); err != nil {
390+
t.Fatalf("Unexpected error when reading response: %s", err)
391+
}
392+
if !(resp.Header.StatusCode() == fasthttp.StatusNotFound) {
393+
t.Errorf("NotFound behavior failed with router chaining.")
394+
t.FailNow()
395+
}
396+
}
397+
312398
func TestRouterOPTIONS(t *testing.T) {
313399
// TODO: because fasthttp is not support OPTIONS method now,
314400
// these test cases will be used in the future.

0 commit comments

Comments
 (0)