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: Make URI modifications more transactional (#2891)
Before, modifying the path might have affected how a new query string was built if the query string relied on the path. Now, we build each component in isolation and only change the URI on the request later. Also, prevent trailing & in query string.
Matthew Holt committed
Jan 15, 2020 at 11:44 UTC
07ad4655db5d37635edf36fa91d997d166d306b0
2 files changed
+31
-5
modules/caddyhttp/rewrite/rewrite.go
+21
-5
@@ -112,7 +112,7 @@ func (rewr Rewrite) rewrite(r *http.Request, repl *caddy.Replacer, logger *zap.L
112
r.Method = strings.ToUpper(repl.ReplaceAll(rewr.Method, ""))
113
}
114
115
- // uri (path, query string, and fragment just because)
115
+ // uri (path, query string, and fragment... because why not)
116
if uri := rewr.URI; uri != "" {
117
// find the bounds of each part of the URI that exist
118
pathStart, qsStart, fragStart := -1, -1, -1
@@ -134,14 +134,30 @@ func (rewr Rewrite) rewrite(r *http.Request, repl *caddy.Replacer, logger *zap.L
134
qsEnd = len(uri)
135
}
136
137
+ // build components which are specified, and store them
138
+ // in a temporary variable so that they all read the
139
+ // same version of the URI
140
+ var newPath, newQuery, newFrag string
141
if pathStart >= 0 {
138
- r.URL.Path = repl.ReplaceAll(uri[pathStart:pathEnd], "")
142
+ newPath = repl.ReplaceAll(uri[pathStart:pathEnd], "")
143
}
144
if qsStart >= 0 {
141
- r.URL.RawQuery = buildQueryString(uri[qsStart:qsEnd], repl)
145
+ newQuery = buildQueryString(uri[qsStart:qsEnd], repl)
146
}
147
if fragStart >= 0 {
144
- r.URL.Fragment = repl.ReplaceAll(uri[fragStart:], "")
148
+ newFrag = repl.ReplaceAll(uri[fragStart:], "")
149
+ }
150
+
151
+ // update the URI with the new components
152
+ // only after building them
153
+ if pathStart >= 0 {
154
+ r.URL.Path = newPath
155
+ }
156
+ if qsStart >= 0 {
157
+ r.URL.RawQuery = newQuery
158
+ }
159
+ if fragStart >= 0 {
160
+ r.URL.Fragment = newFrag
161
}
162
}
163
@@ -206,7 +222,7 @@ func buildQueryString(qs string, repl *caddy.Replacer) string {
222
// if previous iteration wrote a value,
223
// that means we are writing a key
224
if wroteVal {
209
- if sb.Len() > 0 {
225
+ if sb.Len() > 0 && len(comp) > 0 {
226
sb.WriteRune('&')
227
}
228
} else {
modules/caddyhttp/rewrite/rewrite_test.go
+10
@@ -63,6 +63,16 @@ func TestRewrite(t *testing.T) {
63
input: newRequest(t, "GET", "/bar"),
64
expect: newRequest(t, "GET", "/foo/bar"),
65
},
66
+ {
67
+ rule: Rewrite{URI: "/index.php?p={http.request.uri.path}"},
68
+ input: newRequest(t, "GET", "/foo/bar"),
69
+ expect: newRequest(t, "GET", "/index.php?p=%2Ffoo%2Fbar"),
70
+ },
71
+ {
72
+ rule: Rewrite{URI: "?a=b&{http.request.uri.query}"},
73
+ input: newRequest(t, "GET", "/"),
74
+ expect: newRequest(t, "GET", "/?a=b"),
75
+ },
76
{
77
rule: Rewrite{URI: "/?c=d"},
78
input: newRequest(t, "GET", "/"),