diff --git a/gin.go b/gin.go index 2e033bf3..98eb319c 100644 --- a/gin.go +++ b/gin.go @@ -101,6 +101,8 @@ type Engine struct { // For example if /foo/ is requested but a route only exists for /foo, the // client is redirected to /foo with http status code 301 for GET requests // and 307 for all other request methods. + // If this field is false then /foo and /foo/ are assumed the same and no redirection will happen, + // both endpoints will use the same handlers. RedirectTrailingSlash bool // RedirectFixedPath if enabled, the router tries to fix the current request path, if no @@ -712,21 +714,39 @@ func (engine *Engine) handleHTTPRequest(c *Context) { } root := t[i].root // Find route in tree - value := root.getValue(rPath, c.params, c.skippedNodes, unescape) - if value.params != nil { - c.Params = *value.params + isRouteFound := func(value nodeValue) bool { + if value.params != nil { + c.Params = *value.params + } + if value.handlers != nil { + c.handlers = value.handlers + c.fullPath = value.fullPath + c.Next() + c.writermem.WriteHeaderNow() + return true + } + return false } - if value.handlers != nil { - c.handlers = value.handlers - c.fullPath = value.fullPath - c.Next() - c.writermem.WriteHeaderNow() + + value := root.getValue(rPath, c.params, c.skippedNodes, unescape) + if isRouteFound(value) { return } + if httpMethod != http.MethodConnect && rPath != "/" { - if value.tsr && engine.RedirectTrailingSlash { - redirectTrailingSlash(c) - return + if value.tsr { + if engine.engine.RedirectTrailingSlash { + redirectTrailingSlash(c) + return + } + newRPath := rPath + "/" + if rPath[len(rPath)-1] == '/' { + newRPath = rPath[:len(rPath)-1] + } + value = root.getValue(newRPath, c.params, c.skippedNodes, unescape) + if isRouteFound(value) { + return + } } if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) { return diff --git a/routes_test.go b/routes_test.go index 1cae3fce..1b71dace 100644 --- a/routes_test.go +++ b/routes_test.go @@ -237,13 +237,13 @@ func TestRouteRedirectTrailingSlash(t *testing.T) { router.RedirectTrailingSlash = false w = PerformRequest(router, http.MethodGet, "/path/") - assert.Equal(t, http.StatusNotFound, w.Code) + assert.Equal(t, http.StatusOK, w.Code) w = PerformRequest(router, http.MethodGet, "/path2") - assert.Equal(t, http.StatusNotFound, w.Code) + assert.Equal(t, http.StatusOK, w.Code) w = PerformRequest(router, http.MethodPost, "/path3/") - assert.Equal(t, http.StatusNotFound, w.Code) + assert.Equal(t, http.StatusOK, w.Code) w = PerformRequest(router, http.MethodPut, "/path4") - assert.Equal(t, http.StatusNotFound, w.Code) + assert.Equal(t, http.StatusOK, w.Code) } func TestRouteRedirectFixedPath(t *testing.T) {