From ef912dd76ebe9d9848c6e0fd80eaebccc9a11631 Mon Sep 17 00:00:00 2001 From: tomare Date: Thu, 27 Dec 2018 19:42:16 -0500 Subject: [PATCH] [bugfix] Clear matchErr when traversing subrouters. Previously, when searching for a match, matchErr would be erroneously set, and prevent middleware from running (no match == no middleware runs). This fix clears matchErr before traversing the next subrouter in a multi-subrouter router. --- middleware_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++ route.go | 5 ++++ 2 files changed, 65 insertions(+) diff --git a/middleware_test.go b/middleware_test.go index acf4e16..b708be0 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -375,3 +375,63 @@ func TestCORSMethodMiddleware(t *testing.T) { } } } + +func TestMiddlewareOnMultiSubrouter(t *testing.T) { + first := "first" + second := "second" + notFound := "404 not found" + + router := NewRouter() + firstSubRouter := router.PathPrefix("/").Subrouter() + secondSubRouter := router.PathPrefix("/").Subrouter() + + router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Write([]byte(notFound)) + }) + + firstSubRouter.HandleFunc("/first", func(w http.ResponseWriter, r *http.Request) { + + }) + + secondSubRouter.HandleFunc("/second", func(w http.ResponseWriter, r *http.Request) { + + }) + + firstSubRouter.Use(func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(first)) + h.ServeHTTP(w, r) + }) + }) + + secondSubRouter.Use(func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(second)) + h.ServeHTTP(w, r) + }) + }) + + rw := NewRecorder() + req := newRequest("GET", "/first") + + router.ServeHTTP(rw, req) + if rw.Body.String() != first { + t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", first, rw.Body.String()) + } + + rw = NewRecorder() + req = newRequest("GET", "/second") + + router.ServeHTTP(rw, req) + if rw.Body.String() != second { + t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", second, rw.Body.String()) + } + + rw = NewRecorder() + req = newRequest("GET", "/second/not-exist") + + router.ServeHTTP(rw, req) + if rw.Body.String() != notFound { + t.Fatalf("Notfound handler did not run: expected %s for not-exist, (got %s)", notFound, rw.Body.String()) + } +} diff --git a/route.go b/route.go index acef919..a197096 100644 --- a/route.go +++ b/route.go @@ -43,6 +43,11 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { return false } + // Set MatchErr to nil to prevent + // subsequent matching subrouters from failing to run middleware. + // If not reset, the middleware would see a non-nil MatchErr and be skipped, + // even when there was a matching route. + match.MatchErr = nil var matchErr error // Match everything.