diff --git a/pkg/api/route_register.go b/pkg/api/route_register.go index a1e5d20d892..3617ea46aa2 100644 --- a/pkg/api/route_register.go +++ b/pkg/api/route_register.go @@ -6,18 +6,26 @@ import ( macaron "gopkg.in/macaron.v1" ) +type Router interface { + Route(pattern, method string, handlers ...macaron.Handler) +} + type RouteRegister interface { Get(string, ...macaron.Handler) Post(string, ...macaron.Handler) Delete(string, ...macaron.Handler) Put(string, ...macaron.Handler) + Group(string, func(RouteRegister), ...macaron.Handler) + + Register(Router) } -func newRouteRegister(rr *macaron.Router) RouteRegister { +func newRouteRegister() RouteRegister { return &routeRegister{ - prefix: "", - routes: []route{}, + prefix: "", + routes: []route{}, + subfixHandlers: []macaron.Handler{}, } } @@ -31,56 +39,50 @@ type routeRegister struct { prefix string subfixHandlers []macaron.Handler routes []route + groups []*routeRegister } func (rr *routeRegister) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) { group := &routeRegister{ prefix: rr.prefix + pattern, - subfixHandlers: handlers, - routes: rr.routes, + subfixHandlers: append(rr.subfixHandlers, handlers...), + routes: []route{}, } fn(group) + rr.groups = append(rr.groups, group) +} + +func (rr *routeRegister) Register(router Router) { + for _, r := range rr.routes { + router.Route(r.pattern, r.method, r.handlers...) + } + + for _, g := range rr.groups { + g.Register(router) + } +} + +func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handler) { + rr.routes = append(rr.routes, route{ + method: method, + pattern: rr.prefix + pattern, + handlers: append(rr.subfixHandlers, handlers...), + }) } func (rr *routeRegister) Get(pattern string, handlers ...macaron.Handler) { - rr.routes = append(rr.routes, route{ - method: http.MethodGet, - pattern: rr.prefix + pattern, - handlers: handlers, - }) - println("get: get ", len(rr.routes)) - rr.routes = rr.routes[:len(rr.routes)-1] + rr.route(pattern, http.MethodGet, handlers...) } func (rr *routeRegister) Post(pattern string, handlers ...macaron.Handler) { - rr.routes = append(rr.routes, route{ - method: http.MethodPost, - pattern: rr.prefix + pattern, - handlers: handlers, - }) - println("get: post ", len(rr.routes)) - - rr.routes = rr.routes[:len(rr.routes)-1] + rr.route(pattern, http.MethodPost, handlers...) } func (rr *routeRegister) Delete(pattern string, handlers ...macaron.Handler) { - rr.routes = append(rr.routes, route{ - method: http.MethodDelete, - pattern: rr.prefix + pattern, - handlers: handlers, - }) - println("get: delete ", len(rr.routes)) - - rr.routes = rr.routes[:len(rr.routes)-1] + rr.route(pattern, http.MethodDelete, handlers...) } func (rr *routeRegister) Put(pattern string, handlers ...macaron.Handler) { - rr.routes = append(rr.routes, route{ - method: http.MethodPut, - pattern: rr.prefix + pattern, - handlers: handlers, - }) - - rr.routes = rr.routes[:len(rr.routes)-1] + rr.route(pattern, http.MethodPut, handlers...) } diff --git a/pkg/api/route_register_test.go b/pkg/api/route_register_test.go index 89dedbc8e65..d296d96b307 100644 --- a/pkg/api/route_register_test.go +++ b/pkg/api/route_register_test.go @@ -1,39 +1,86 @@ package api -import "testing" +import ( + "strconv" + "testing" + + macaron "gopkg.in/macaron.v1" +) + +type fakeRouter struct { + route []route +} + +func (fr *fakeRouter) Route(pattern, method string, handlers ...macaron.Handler) { + fr.route = append(fr.route, route{ + pattern: pattern, + method: method, + handlers: handlers, + }) +} + +func emptyHandlers(n int) []macaron.Handler { + res := []macaron.Handler{} + for i := 1; n >= i; i++ { + res = append(res, emptyHandler(strconv.Itoa(i))) + } + return res +} + +func emptyHandler(name string) macaron.Handler { + return struct{ name string }{name: name} +} func TestRouteRegister(t *testing.T) { - - rr := &routeRegister{ - prefix: "", - routes: []route{}, + testTable := []route{ + {method: "DELETE", pattern: "/admin", handlers: emptyHandlers(1)}, + {method: "GET", pattern: "/down", handlers: emptyHandlers(2)}, + {method: "POST", pattern: "/user", handlers: emptyHandlers(1)}, + {method: "PUT", pattern: "/user/friends", handlers: emptyHandlers(1)}, + {method: "DELETE", pattern: "/user/admin", handlers: emptyHandlers(2)}, + {method: "GET", pattern: "/user/admin/all", handlers: emptyHandlers(4)}, } - rr.Delete("/admin") - rr.Get("/down") + // Setup + rr := newRouteRegister() - rr.Group("/user", func(innerRR RouteRegister) { - innerRR.Delete("") - innerRR.Get("/friends") + rr.Delete("/admin", emptyHandler("1")) + rr.Get("/down", emptyHandler("1"), emptyHandler("2")) + + rr.Group("/user", func(user RouteRegister) { + user.Post("", emptyHandler("1")) + user.Put("/friends", emptyHandler("2")) + + user.Group("/admin", func(admin RouteRegister) { + admin.Delete("", emptyHandler("3")) + admin.Get("/all", emptyHandler("3"), emptyHandler("4"), emptyHandler("5")) + + }, emptyHandler("3")) }) - println("len", len(rr.routes)) + fr := &fakeRouter{} + rr.Register(fr) - if rr.routes[0].pattern != "/admin" && rr.routes[0].method != "DELETE" { - t.Errorf("expected first route to be DELETE /admin") + // Validation + if len(fr.route) != len(testTable) { + t.Errorf("want %v routes, got %v", len(testTable), len(fr.route)) } - if rr.routes[1].pattern != "/down" && rr.routes[1].method != "GET" { - t.Errorf("expected first route to be GET /down") - } + for i, _ := range testTable { + if testTable[i].method != fr.route[i].method { + t.Errorf("want %s got %v", testTable[i].method, fr.route[i].method) + } - println("len", len(rr.routes)) + if testTable[i].pattern != fr.route[i].pattern { + t.Errorf("want %s got %v", testTable[i].pattern, fr.route[i].pattern) + } - if rr.routes[2].pattern != "/user" && rr.routes[2].method != "DELETE" { - t.Errorf("expected first route to be DELETE /admin") - } - - if rr.routes[3].pattern != "/user/friends" && rr.routes[3].method != "GET" { - t.Errorf("expected first route to be GET /down") + if len(testTable[i].handlers) != len(fr.route[i].handlers) { + t.Errorf("want %d handlers got %d handlers \ntestcase: %v\nroute: %v\n", + len(testTable[i].handlers), + len(fr.route[i].handlers), + testTable[i], + fr.route[i]) + } } }