diff --git a/pkg/api/api.go b/pkg/api/api.go index b1af24ff907..47cfb616142 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -21,7 +21,7 @@ func (hs *HttpServer) registerRoutes() { // automatically set HEAD for every GET macaronR.SetAutoHead(true) - r := newRouteRegister() + r := newRouteRegister(middleware.RequestMetrics) // not logged in views r.Get("/", reqSignedIn, Index) diff --git a/pkg/api/route_register.go b/pkg/api/route_register.go index b36c06b3b07..b23c92ed1c0 100644 --- a/pkg/api/route_register.go +++ b/pkg/api/route_register.go @@ -3,7 +3,6 @@ package api import ( "net/http" - "github.com/grafana/grafana/pkg/middleware" macaron "gopkg.in/macaron.v1" ) @@ -24,11 +23,14 @@ type RouteRegister interface { Register(Router) *macaron.Router } -func newRouteRegister() RouteRegister { +type RegisterNamedMiddleware func(name string) macaron.Handler + +func newRouteRegister(namedMiddleware ...RegisterNamedMiddleware) RouteRegister { return &routeRegister{ - prefix: "", - routes: []route{}, - subfixHandlers: []macaron.Handler{}, + prefix: "", + routes: []route{}, + subfixHandlers: []macaron.Handler{}, + namedMiddleware: namedMiddleware, } } @@ -39,17 +41,19 @@ type route struct { } type routeRegister struct { - prefix string - subfixHandlers []macaron.Handler - routes []route - groups []*routeRegister + prefix string + subfixHandlers []macaron.Handler + namedMiddleware []RegisterNamedMiddleware + routes []route + groups []*routeRegister } func (rr *routeRegister) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) { group := &routeRegister{ - prefix: rr.prefix + pattern, - subfixHandlers: append(rr.subfixHandlers, handlers...), - routes: []route{}, + prefix: rr.prefix + pattern, + subfixHandlers: append(rr.subfixHandlers, handlers...), + routes: []route{}, + namedMiddleware: rr.namedMiddleware, } fn(group) @@ -71,8 +75,13 @@ func (rr *routeRegister) Register(router Router) *macaron.Router { func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handler) { //inject tracing - h := append(rr.subfixHandlers, handlers...) - h = append([]macaron.Handler{middleware.RequestMetrics(pattern)}, h...) + h := make([]macaron.Handler, 0) + for _, fn := range rr.namedMiddleware { + h = append(h, fn(pattern)) + } + + h = append(h, rr.subfixHandlers...) + h = append(h, handlers...) rr.routes = append(rr.routes, route{ method: method, diff --git a/pkg/api/route_register_test.go b/pkg/api/route_register_test.go index f0446ef534f..27b135c9a47 100644 --- a/pkg/api/route_register_test.go +++ b/pkg/api/route_register_test.go @@ -33,7 +33,48 @@ func emptyHandler(name string) macaron.Handler { return struct{ name string }{name: name} } -func TestRouteRegister(t *testing.T) { +func TestRouteSimpleRegister(t *testing.T) { + testTable := []route{ + {method: "DELETE", pattern: "/admin", handlers: emptyHandlers(2)}, + {method: "GET", pattern: "/down", handlers: emptyHandlers(3)}, + } + + // Setup + rr := newRouteRegister(func(name string) macaron.Handler { + return emptyHandler(name) + }) + + rr.Delete("/admin", emptyHandler("1")) + rr.Get("/down", emptyHandler("1"), emptyHandler("2")) + + fr := &fakeRouter{} + rr.Register(fr) + + // Validation + if len(fr.route) != len(testTable) { + t.Errorf("want %v routes, got %v", len(testTable), len(fr.route)) + } + + 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) + } + + if testTable[i].pattern != fr.route[i].pattern { + t.Errorf("want %s got %v", testTable[i].pattern, fr.route[i].pattern) + } + + 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]) + } + } +} + +func TestRouteGroupedRegister(t *testing.T) { testTable := []route{ {method: "DELETE", pattern: "/admin", handlers: emptyHandlers(1)}, {method: "GET", pattern: "/down", handlers: emptyHandlers(2)}, @@ -86,3 +127,59 @@ func TestRouteRegister(t *testing.T) { } } } + +func TestNamedMiddlewareRouteRegister(t *testing.T) { + testTable := []route{ + {method: "DELETE", pattern: "/admin", handlers: emptyHandlers(2)}, + {method: "GET", pattern: "/down", handlers: emptyHandlers(3)}, + {method: "POST", pattern: "/user", handlers: emptyHandlers(2)}, + {method: "PUT", pattern: "/user/friends", handlers: emptyHandlers(2)}, + {method: "DELETE", pattern: "/user/admin", handlers: emptyHandlers(3)}, + {method: "GET", pattern: "/user/admin/all", handlers: emptyHandlers(5)}, + } + + // Setup + rr := newRouteRegister(func(name string) macaron.Handler { + return emptyHandler(name) + }) + + 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")) + }) + + fr := &fakeRouter{} + rr.Register(fr) + + // Validation + if len(fr.route) != len(testTable) { + t.Errorf("want %v routes, got %v", len(testTable), len(fr.route)) + } + + 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) + } + + if testTable[i].pattern != fr.route[i].pattern { + t.Errorf("want %s got %v", testTable[i].pattern, fr.route[i].pattern) + } + + 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]) + } + } +}