@marcel91200 / caddy Mirror · read-only / commits / 88a38bd0
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

rewrite: Use RawPath instead of Path (fix #3596) (#3918)

Prevent information loss, i.e. the encoded form that was sent by the client, when using URL strip/replace.

go-d committed Jan 11, 2021 at 17:18 UTC 88a38bd00d386457aec71696a386449d3bcf8990
2 files changed +37 -11
modules/caddyhttp/rewrite/rewrite.go
+22 -11
@@ -191,11 +191,21 @@ func (rewr Rewrite) rewrite(r *http.Request, repl *caddy.Replacer, logger *zap.L
191 // strip path prefix or suffix
192 if rewr.StripPathPrefix != "" {
193 prefix := repl.ReplaceAll(rewr.StripPathPrefix, "")
194 - r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
194 + r.URL.RawPath = strings.TrimPrefix(r.URL.RawPath, prefix)
195 + if p, err := url.PathUnescape(r.URL.RawPath); err == nil && p != "" {
196 + r.URL.Path = p
197 + } else {
198 + r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
199 + }
200 }
201 if rewr.StripPathSuffix != "" {
202 suffix := repl.ReplaceAll(rewr.StripPathSuffix, "")
198 - r.URL.Path = strings.TrimSuffix(r.URL.Path, suffix)
203 + r.URL.RawPath = strings.TrimSuffix(r.URL.RawPath, suffix)
204 + if p, err := url.PathUnescape(r.URL.RawPath); err == nil && p != "" {
205 + r.URL.Path = p
206 + } else {
207 + r.URL.Path = strings.TrimSuffix(r.URL.Path, suffix)
208 + }
209 }
210
211 // substring replacements in URI
@@ -289,10 +299,10 @@ type replacer struct {
299 Limit int `json:"limit,omitempty"`
300 }
301
292 -// do performs the replacement on r and returns true if any changes were made.
293 -func (rep replacer) do(r *http.Request, repl *caddy.Replacer) bool {
302 +// do performs the replacement on r.
303 +func (rep replacer) do(r *http.Request, repl *caddy.Replacer) {
304 if rep.Find == "" || rep.Replace == "" {
295 - return false
305 + return
306 }
307
308 lim := rep.Limit
@@ -303,13 +313,14 @@ func (rep replacer) do(r *http.Request, repl *caddy.Replacer) bool {
313 find := repl.ReplaceAll(rep.Find, "")
314 replace := repl.ReplaceAll(rep.Replace, "")
315
306 - oldPath := r.URL.Path
307 - oldQuery := r.URL.RawQuery
308 -
309 - r.URL.Path = strings.Replace(oldPath, find, replace, lim)
310 - r.URL.RawQuery = strings.Replace(oldQuery, find, replace, lim)
316 + r.URL.RawPath = strings.Replace(r.URL.RawPath, find, replace, lim)
317 + if p, err := url.PathUnescape(r.URL.RawPath); err == nil && p != "" {
318 + r.URL.Path = p
319 + } else {
320 + r.URL.Path = strings.Replace(r.URL.Path, find, replace, lim)
321 + }
322
312 - return r.URL.Path != oldPath && r.URL.RawQuery != oldQuery
323 + r.URL.RawQuery = strings.Replace(r.URL.RawQuery, find, replace, lim)
324 }
325
326 // Interface guard
modules/caddyhttp/rewrite/rewrite_test.go
+15
@@ -199,6 +199,11 @@ func TestRewrite(t *testing.T) {
199 input: newRequest(t, "GET", "/prefix/foo/bar"),
200 expect: newRequest(t, "GET", "/foo/bar"),
201 },
202 + {
203 + rule: Rewrite{StripPathPrefix: "/prefix"},
204 + input: newRequest(t, "GET", "/prefix/foo%2Fbar"),
205 + expect: newRequest(t, "GET", "/foo%2Fbar"),
206 + },
207 {
208 rule: Rewrite{StripPathPrefix: "/prefix"},
209 input: newRequest(t, "GET", "/foo/prefix/bar"),
@@ -215,6 +220,11 @@ func TestRewrite(t *testing.T) {
220 input: newRequest(t, "GET", "/foo/bar/suffix"),
221 expect: newRequest(t, "GET", "/foo/bar/"),
222 },
223 + {
224 + rule: Rewrite{StripPathSuffix: "suffix"},
225 + input: newRequest(t, "GET", "/foo%2Fbar/suffix"),
226 + expect: newRequest(t, "GET", "/foo%2Fbar/"),
227 + },
228 {
229 rule: Rewrite{StripPathSuffix: "/suffix"},
230 input: newRequest(t, "GET", "/foo/suffix/bar"),
@@ -231,6 +241,11 @@ func TestRewrite(t *testing.T) {
241 input: newRequest(t, "GET", "/foo/findme/bar"),
242 expect: newRequest(t, "GET", "/foo/replaced/bar"),
243 },
244 + {
245 + rule: Rewrite{URISubstring: []replacer{{Find: "findme", Replace: "replaced"}}},
246 + input: newRequest(t, "GET", "/foo/findme%2Fbar"),
247 + expect: newRequest(t, "GET", "/foo/replaced%2Fbar"),
248 + },
249 } {
250 // copy the original input just enough so that we can
251 // compare it after the rewrite to see if it changed