diff --git a/pkg/middlewares/replacepath/replace_path.go b/pkg/middlewares/replacepath/replace_path.go index a7e82826a..d730a931c 100644 --- a/pkg/middlewares/replacepath/replace_path.go +++ b/pkg/middlewares/replacepath/replace_path.go @@ -41,12 +41,12 @@ func (r *replacePath) GetTracingInformation() (string, ext.SpanKindEnum) { } func (r *replacePath) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - if req.URL.RawPath == "" { - req.Header.Add(ReplacedPathHeader, req.URL.Path) - } else { - req.Header.Add(ReplacedPathHeader, req.URL.RawPath) + currentPath := req.URL.RawPath + if currentPath == "" { + currentPath = req.URL.EscapedPath() } + req.Header.Add(ReplacedPathHeader, currentPath) req.URL.RawPath = r.path var err error diff --git a/pkg/middlewares/replacepath/replace_path_test.go b/pkg/middlewares/replacepath/replace_path_test.go index 657b1c3b8..782733bc0 100644 --- a/pkg/middlewares/replacepath/replace_path_test.go +++ b/pkg/middlewares/replacepath/replace_path_test.go @@ -60,6 +60,16 @@ func TestReplacePath(t *testing.T) { expectedRawPath: "/foo%2Fbar", expectedHeader: "/path", }, + { + desc: "replacement with percent encoded backspace char", + path: "/path/%08bar", + config: dynamic.ReplacePath{ + Path: "/path/%08bar", + }, + expectedPath: "/path/\bbar", + expectedRawPath: "/path/%08bar", + expectedHeader: "/path/%08bar", + }, } for _, test := range testCases { diff --git a/pkg/middlewares/replacepathregex/replace_path_regex.go b/pkg/middlewares/replacepathregex/replace_path_regex.go index 4a10fc1c9..fea6fa2de 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex.go @@ -16,9 +16,7 @@ import ( "github.com/traefik/traefik/v2/pkg/tracing" ) -const ( - typeName = "ReplacePathRegex" -) +const typeName = "ReplacePathRegex" // ReplacePathRegex is a middleware used to replace the path of a URL request with a regular expression. type replacePathRegex struct { @@ -50,16 +48,13 @@ func (rp *replacePathRegex) GetTracingInformation() (string, ext.SpanKindEnum) { } func (rp *replacePathRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - var currentPath string - if req.URL.RawPath == "" { - currentPath = req.URL.Path - } else { - currentPath = req.URL.RawPath + currentPath := req.URL.RawPath + if currentPath == "" { + currentPath = req.URL.EscapedPath() } if rp.regexp != nil && len(rp.replacement) > 0 && rp.regexp.MatchString(currentPath) { req.Header.Add(replacepath.ReplacedPathHeader, currentPath) - req.URL.RawPath = rp.regexp.ReplaceAllString(currentPath, rp.replacement) // as replacement can introduce escaped characters diff --git a/pkg/middlewares/replacepathregex/replace_path_regex_test.go b/pkg/middlewares/replacepathregex/replace_path_regex_test.go index c22083ea5..59018d784 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex_test.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex_test.go @@ -106,6 +106,16 @@ func TestReplacePathRegex(t *testing.T) { expectedPath: "/aaa/bbb", expectedRawPath: "/aaa%2Fbbb", }, + { + desc: "path with percent encoded backspace char", + path: "/foo/%08bar", + config: dynamic.ReplacePathRegex{ + Replacement: "/$1", + Regex: `^/foo/(.*)`, + }, + expectedPath: "/\bbar", + expectedRawPath: "/%08bar", + }, } for _, test := range testCases {