From c1498bc6d749a5e22d6f0b30230b39b6ace3ff89 Mon Sep 17 00:00:00 2001 From: Valentin Krasontovitsch Date: Wed, 25 Apr 2018 13:29:12 +0200 Subject: [PATCH] Feat: Pass encoded characters in path unchanged We enable passing substrings that represent encoded reserved symbols, like `%2f` for `/`, in the path of a request. NB: This does not enable using encoded characters in rewrite rules (e.g. in the urlprefix directive). Cf. #347 and #486 --- route/target.go | 17 +++++++++++++++++ route/target_test.go | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/route/target.go b/route/target.go index db9e5244b..2109aed9f 100644 --- a/route/target.go +++ b/route/target.go @@ -64,20 +64,37 @@ func (t *Target) BuildRedirectURL(requestURL *url.URL) { Scheme: t.URL.Scheme, Host: t.URL.Host, Path: t.URL.Path, + RawPath: t.URL.Path, RawQuery: t.URL.RawQuery, } + // treat case of $path not separated with a / from host if strings.HasSuffix(t.RedirectURL.Host, "$path") { t.RedirectURL.Host = t.RedirectURL.Host[:len(t.RedirectURL.Host)-len("$path")] t.RedirectURL.Path = "$path" } + // remove / before $path in redirect url if strings.Contains(t.RedirectURL.Path, "/$path") { t.RedirectURL.Path = strings.Replace(t.RedirectURL.Path, "/$path", "$path", 1) + t.RedirectURL.RawPath = strings.Replace(t.RedirectURL.RawPath, "/$path", "$path", 1) } + // insert passed request path, remove strip path, set quer if strings.Contains(t.RedirectURL.Path, "$path") { + // replace in not raw path t.RedirectURL.Path = strings.Replace(t.RedirectURL.Path, "$path", requestURL.Path, 1) + // replace in raw path - determine replacement first + var replaceRawPath string + if requestURL.RawPath == "" { + replaceRawPath = requestURL.Path + } else { + replaceRawPath = requestURL.RawPath + } + t.RedirectURL.RawPath = strings.Replace(t.RedirectURL.RawPath, "$path", replaceRawPath, 1) + // remove stip path if t.StripPath != "" && strings.HasPrefix(t.RedirectURL.Path, t.StripPath) { t.RedirectURL.Path = t.RedirectURL.Path[len(t.StripPath):] + t.RedirectURL.RawPath = t.RedirectURL.RawPath[len(t.StripPath):] } + // set query if t.RedirectURL.RawQuery == "" && requestURL.RawQuery != "" { t.RedirectURL.RawQuery = requestURL.RawQuery } diff --git a/route/target_test.go b/route/target_test.go index 21ad2bc42..41ab8d14f 100644 --- a/route/target_test.go +++ b/route/target_test.go @@ -72,6 +72,16 @@ func TestTarget_BuildRedirectURL(t *testing.T) { {req: "/abc/?aaa=1", want: "http://bar.com/bbb/abc/?aaa=1"}, }, }, + { // simple redirect to corresponding path with encoded char in path + route: "route add svc / http://bar.com/$path", + tests: []routeTest{ + {req: "/%20", want: "http://bar.com/%20"}, + {req: "/a%2fbc", want: "http://bar.com/a%2fbc"}, + {req: "/a/b%22/c", want: "http://bar.com/a/b%22/c"}, + {req: "/%2f/?aaa=1", want: "http://bar.com/%2f/?aaa=1"}, + {req: "/%20/a%2f/", want: "http://bar.com/%20/a%2f/"}, + }, + }, { // strip prefix route: "route add svc /stripme http://bar.com/$path opts \"strip=/stripme\"", tests: []routeTest{