From ab57d851d6db97c85c411a2b05f7f928fc412b7d Mon Sep 17 00:00:00 2001 From: Taichi Sasaki Date: Tue, 26 Sep 2023 22:47:08 +0900 Subject: [PATCH 1/3] Test redirection for URLs with trailing slashes --- http/mux_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/http/mux_test.go b/http/mux_test.go index f3eacc1798..94f59781db 100644 --- a/http/mux_test.go +++ b/http/mux_test.go @@ -227,6 +227,16 @@ func TestResolvePattern(t *testing.T) { w := httptest.NewRecorder() mux.ServeHTTP(w, req) assert.True(t, called) + // Make sure the URL with a trailing slash is redirected. + called = false // Reset. + req, _ = http.NewRequest("GET", c.URL+"/", nil) + w = httptest.NewRecorder() + mux.ServeHTTP(w, req) + assert.Equal(t, http.StatusMovedPermanently, w.Code) + req, _ = http.NewRequest("GET", w.Header().Get("Location"), nil) + w = httptest.NewRecorder() + mux.ServeHTTP(w, req) + assert.True(t, called) }) } } From 2a1790dd5f25f9eaaf40cfcf32229792220c7df6 Mon Sep 17 00:00:00 2001 From: Taichi Sasaki Date: Tue, 26 Sep 2023 22:49:49 +0900 Subject: [PATCH 2/3] Use RedirectSlashes middleware by default Goa mux --- http/mux.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/http/mux.go b/http/mux.go index f918c877fd..8098b2bdb0 100644 --- a/http/mux.go +++ b/http/mux.go @@ -8,6 +8,7 @@ import ( "regexp" chi "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" ) type ( @@ -85,6 +86,7 @@ func NewMuxer() ResolverMuxer { w.WriteHeader(http.StatusNotFound) enc.Encode(NewErrorResponse(ctx, fmt.Errorf("404 page not found"))) // nolint:errcheck })) + r.Use(middleware.RedirectSlashes) return &mux{Router: r, wildcards: make(map[string]string)} } From 3fbf066e93645b3640f49a1abd29c4cc8a1299fd Mon Sep 17 00:00:00 2001 From: Taichi Sasaki Date: Wed, 27 Sep 2023 10:11:06 +0900 Subject: [PATCH 3/3] Mount at the top level of the router --- http/mux.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/http/mux.go b/http/mux.go index 8098b2bdb0..11013ecb3a 100644 --- a/http/mux.go +++ b/http/mux.go @@ -80,13 +80,15 @@ type ( // NewMuxer returns a Muxer implementation based on a Chi router. func NewMuxer() ResolverMuxer { r := chi.NewRouter() + // RedirectSlashes must be mounted at the top level of the router. + // See. https://github.com/go-chi/chi/blob/1129e362d6cce6e3805e3bc8dfbaeb34b5129789/middleware/strip_test.go#L105-L107 + r.Use(middleware.RedirectSlashes) r.NotFound(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ctx := context.WithValue(req.Context(), AcceptTypeKey, req.Header.Get("Accept")) enc := ResponseEncoder(ctx, w) w.WriteHeader(http.StatusNotFound) enc.Encode(NewErrorResponse(ctx, fmt.Errorf("404 page not found"))) // nolint:errcheck })) - r.Use(middleware.RedirectSlashes) return &mux{Router: r, wildcards: make(map[string]string)} }