From b6425689dc657ad20762ada1591ebcc50f668c09 Mon Sep 17 00:00:00 2001 From: Dan Markham Date: Tue, 7 May 2019 04:32:35 -0700 Subject: [PATCH] Clean the Request Path early (#1817) This will reduce the number of times we have todo a redirect. and allow multiple slashes in path to be routed! fixes #1644 --- gin.go | 1 + routes_test.go | 52 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/gin.go b/gin.go index 2d24092..4dbe983 100644 --- a/gin.go +++ b/gin.go @@ -372,6 +372,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) { rPath = c.Request.URL.RawPath unescape = engine.UnescapePathValues } + rPath = cleanPath(rPath) // Find root of the tree for the given HTTP method t := engine.trees diff --git a/routes_test.go b/routes_test.go index de363a8..e16c137 100644 --- a/routes_test.go +++ b/routes_test.go @@ -22,7 +22,7 @@ type header struct { } func performRequest(r http.Handler, method, path string, headers ...header) *httptest.ResponseRecorder { - req, _ := http.NewRequest(method, path, nil) + req := httptest.NewRequest(method, path, nil) for _, h := range headers { req.Header.Add(h.Key, h.Value) } @@ -257,6 +257,39 @@ func TestRouteParamsByName(t *testing.T) { assert.Equal(t, "/is/super/great", wild) } +// TestContextParamsGet tests that a parameter can be parsed from the URL even with extra slashes. +func TestRouteParamsByNameWithExtraSlash(t *testing.T) { + name := "" + lastName := "" + wild := "" + router := New() + router.GET("/test/:name/:last_name/*wild", func(c *Context) { + name = c.Params.ByName("name") + lastName = c.Params.ByName("last_name") + var ok bool + wild, ok = c.Params.Get("wild") + + assert.True(t, ok) + assert.Equal(t, name, c.Param("name")) + assert.Equal(t, name, c.Param("name")) + assert.Equal(t, lastName, c.Param("last_name")) + + assert.Empty(t, c.Param("wtf")) + assert.Empty(t, c.Params.ByName("wtf")) + + wtf, ok := c.Params.Get("wtf") + assert.Empty(t, wtf) + assert.False(t, ok) + }) + + w := performRequest(router, "GET", "//test//john//smith//is//super//great") + + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "john", name) + assert.Equal(t, "smith", lastName) + assert.Equal(t, "/is/super/great", wild) +} + // TestHandleStaticFile - ensure the static file handles properly func TestRouteStaticFile(t *testing.T) { // SETUP file @@ -386,15 +419,14 @@ func TestRouterNotFound(t *testing.T) { code int location string }{ - {"/path/", http.StatusMovedPermanently, "/path"}, // TSR -/ - {"/dir", http.StatusMovedPermanently, "/dir/"}, // TSR +/ - {"", http.StatusMovedPermanently, "/"}, // TSR +/ - {"/PATH", http.StatusMovedPermanently, "/path"}, // Fixed Case - {"/DIR/", http.StatusMovedPermanently, "/dir/"}, // Fixed Case - {"/PATH/", http.StatusMovedPermanently, "/path"}, // Fixed Case -/ - {"/DIR", http.StatusMovedPermanently, "/dir/"}, // Fixed Case +/ - {"/../path", http.StatusMovedPermanently, "/path"}, // CleanPath - {"/nope", http.StatusNotFound, ""}, // NotFound + {"/path/", http.StatusMovedPermanently, "/path"}, // TSR -/ + {"/dir", http.StatusMovedPermanently, "/dir/"}, // TSR +/ + {"/PATH", http.StatusMovedPermanently, "/path"}, // Fixed Case + {"/DIR/", http.StatusMovedPermanently, "/dir/"}, // Fixed Case + {"/PATH/", http.StatusMovedPermanently, "/path"}, // Fixed Case -/ + {"/DIR", http.StatusMovedPermanently, "/dir/"}, // Fixed Case +/ + {"/../path", http.StatusOK, ""}, // CleanPath + {"/nope", http.StatusNotFound, ""}, // NotFound } for _, tr := range testRoutes { w := performRequest(router, "GET", tr.route)