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