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
This commit is contained in:
Dan Markham 2019-05-07 04:32:35 -07:00 committed by 田欧
parent 66d2c30c54
commit b6425689dc
2 changed files with 43 additions and 10 deletions

1
gin.go
View File

@ -372,6 +372,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) {
rPath = c.Request.URL.RawPath rPath = c.Request.URL.RawPath
unescape = engine.UnescapePathValues unescape = engine.UnescapePathValues
} }
rPath = cleanPath(rPath)
// Find root of the tree for the given HTTP method // Find root of the tree for the given HTTP method
t := engine.trees t := engine.trees

View File

@ -22,7 +22,7 @@ type header struct {
} }
func performRequest(r http.Handler, method, path string, headers ...header) *httptest.ResponseRecorder { 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 { for _, h := range headers {
req.Header.Add(h.Key, h.Value) req.Header.Add(h.Key, h.Value)
} }
@ -257,6 +257,39 @@ func TestRouteParamsByName(t *testing.T) {
assert.Equal(t, "/is/super/great", wild) 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 // TestHandleStaticFile - ensure the static file handles properly
func TestRouteStaticFile(t *testing.T) { func TestRouteStaticFile(t *testing.T) {
// SETUP file // SETUP file
@ -388,12 +421,11 @@ func TestRouterNotFound(t *testing.T) {
}{ }{
{"/path/", http.StatusMovedPermanently, "/path"}, // TSR -/ {"/path/", http.StatusMovedPermanently, "/path"}, // TSR -/
{"/dir", http.StatusMovedPermanently, "/dir/"}, // TSR +/ {"/dir", http.StatusMovedPermanently, "/dir/"}, // TSR +/
{"", http.StatusMovedPermanently, "/"}, // TSR +/
{"/PATH", http.StatusMovedPermanently, "/path"}, // Fixed Case {"/PATH", http.StatusMovedPermanently, "/path"}, // Fixed Case
{"/DIR/", http.StatusMovedPermanently, "/dir/"}, // Fixed Case {"/DIR/", http.StatusMovedPermanently, "/dir/"}, // Fixed Case
{"/PATH/", http.StatusMovedPermanently, "/path"}, // Fixed Case -/ {"/PATH/", http.StatusMovedPermanently, "/path"}, // Fixed Case -/
{"/DIR", http.StatusMovedPermanently, "/dir/"}, // Fixed Case +/ {"/DIR", http.StatusMovedPermanently, "/dir/"}, // Fixed Case +/
{"/../path", http.StatusMovedPermanently, "/path"}, // CleanPath {"/../path", http.StatusOK, ""}, // CleanPath
{"/nope", http.StatusNotFound, ""}, // NotFound {"/nope", http.StatusNotFound, ""}, // NotFound
} }
for _, tr := range testRoutes { for _, tr := range testRoutes {