Skip to content

Commit

Permalink
allow router to use request.URL.RawPath
Browse files Browse the repository at this point in the history
  • Loading branch information
halorium committed Jul 26, 2017
1 parent 975b5c4 commit 4c99d66
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
12 changes: 12 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ type Router struct {
// The handler can be used to keep your server from crashing because of
// unrecovered panics.
PanicHandler func(http.ResponseWriter, *http.Request, interface{})

// Go 1.5 introduced the RawPath field in net/url to hold the encoded form of Path.
// The Parse function sets both Path and RawPath in the URL it returns,
// and URL's String method uses RawPath if it is a valid encoding of Path,
// by calling the EncodedPath method.
// This tells the router to use the request.URL.RawPath when parsing the path.
UseRawPath bool
}

// Make sure the Router conforms with the http.Handler interface
Expand All @@ -172,6 +179,7 @@ func New() *Router {
RedirectFixedPath: true,
HandleMethodNotAllowed: true,
HandleOPTIONS: true,
UseRawPath: false,
}
}

Expand Down Expand Up @@ -339,6 +347,10 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {

path := req.URL.Path

if r.UseRawPath {
path = req.URL.RawPath
}

if root := r.trees[req.Method]; root != nil {
if handle, ps, tsr := root.getValue(path); handle != nil {
handle(w, req, ps)
Expand Down
45 changes: 45 additions & 0 deletions router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,48 @@ func TestRouterServeFiles(t *testing.T) {
t.Error("serving file failed")
}
}

func TestRouterUseRawPathSuccess(t *testing.T) {
router := New()
router.UseRawPath = true

routed := false
router.Handle("GET", "/user/:name", func(w http.ResponseWriter, r *http.Request, ps Params) {
routed = true
want := Params{Param{"name", "abc/123"}}
if !reflect.DeepEqual(ps, want) {
t.Fatalf("wrong wildcard values: want %v, got %v", want, ps)
}
})

w := new(mockResponseWriter)

req, _ := http.NewRequest("GET", "/user/abc%2F123", nil)
router.ServeHTTP(w, req)

if !routed {
t.Fatal("routing failed")
}
}

func TestRouterUseRawPathFailure(t *testing.T) {
router := New()

routed := false
router.Handle("GET", "/user/:name", func(w http.ResponseWriter, r *http.Request, ps Params) {
routed = true
want := Params{Param{"name", "abc/123"}}
if !reflect.DeepEqual(ps, want) {
t.Fatalf("wrong wildcard values: want %v, got %v", want, ps)
}
})

w := new(mockResponseWriter)

req, _ := http.NewRequest("GET", "/user/abc%2F123", nil)
router.ServeHTTP(w, req)

if routed {
t.Fatal("routing unexpectedly succeeded")
}
}
8 changes: 7 additions & 1 deletion tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package httprouter

import (
"net/url"
"strings"
"unicode"
"unicode/utf8"
Expand Down Expand Up @@ -371,7 +372,12 @@ walk: // outer loop for walking the tree
i := len(p)
p = p[:i+1] // expand slice within preallocated capacity
p[i].Key = n.path[1:]
p[i].Value = path[:end]

value, err := url.PathUnescape(path[:end])
if err != nil {
return
}
p[i].Value = value

// we need to go deeper!
if end < len(path) {
Expand Down
1 change: 1 addition & 0 deletions tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ func TestTreeWildcard(t *testing.T) {
{"/files/js/inc/framework.js", false, "/files/:dir/*filepath", Params{Param{"dir", "js"}, Param{"filepath", "/inc/framework.js"}}},
{"/info/gordon/public", false, "/info/:user/public", Params{Param{"user", "gordon"}}},
{"/info/gordon/project/go", false, "/info/:user/project/:project", Params{Param{"user", "gordon"}, Param{"project", "go"}}},
{"/search/something%2Fencoded", false, "/search/:query", Params{Param{"query", "something/encoded"}}},
})

checkPriorities(t, tree)
Expand Down

0 comments on commit 4c99d66

Please sign in to comment.