Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 18:00 UTC
rewrite: Handle fragment before query (fix #4775)
Matthew Holt committed
May 9, 2022 at 11:09 UTC
693e9b5283e675b56084ecc83d73176cab0ee27c
2 files changed
+22
-4
modules/caddyhttp/rewrite/rewrite.go
+10
-3
@@ -135,13 +135,20 @@ func (rewr Rewrite) Rewrite(r *http.Request, repl *caddy.Replacer) bool {
135
// find the bounds of each part of the URI that exist
136
pathStart, qsStart, fragStart := -1, -1, -1
137
pathEnd, qsEnd := -1, -1
138
+ loop:
139
for i, ch := range uri {
140
switch {
141
case ch == '?' && qsStart < 0:
142
pathEnd, qsStart = i, i+1
142
- case ch == '#' && fragStart < 0:
143
- qsEnd, fragStart = i, i+1
144
- case pathStart < 0 && qsStart < 0 && fragStart < 0:
143
+ case ch == '#' && fragStart < 0: // everything after fragment is fragment (very clear in RFC 3986 section 4.2)
144
+ if qsStart < 0 {
145
+ pathEnd = i
146
+ } else {
147
+ qsEnd = i
148
+ }
149
+ fragStart = i + 1
150
+ break loop
151
+ case pathStart < 0 && qsStart < 0:
152
pathStart = i
153
}
154
}
modules/caddyhttp/rewrite/rewrite_test.go
+12
-1
@@ -204,6 +204,16 @@ func TestRewrite(t *testing.T) {
204
input: newRequest(t, "GET", "/%C2%B7%E2%88%B5.png?a=b"),
205
expect: newRequest(t, "GET", "/i/%C2%B7%E2%88%B5.png?a=b"),
206
},
207
+ {
208
+ rule: Rewrite{URI: "/bar#?"},
209
+ input: newRequest(t, "GET", "/foo#fragFirst?c=d"), // not a valid query string (is part of fragment)
210
+ expect: newRequest(t, "GET", "/bar#?"), // I think this is right? but who knows; std lib drops fragment when parsing
211
+ },
212
+ {
213
+ rule: Rewrite{URI: "/bar"},
214
+ input: newRequest(t, "GET", "/foo#fragFirst?c=d"),
215
+ expect: newRequest(t, "GET", "/bar#fragFirst?c=d"),
216
+ },
217
218
{
219
rule: Rewrite{StripPathPrefix: "/prefix"},
@@ -271,10 +281,11 @@ func TestRewrite(t *testing.T) {
281
} {
282
// copy the original input just enough so that we can
283
// compare it after the rewrite to see if it changed
284
+ urlCopy := *tc.input.URL
285
originalInput := &http.Request{
286
Method: tc.input.Method,
287
RequestURI: tc.input.RequestURI,
277
- URL: &*tc.input.URL,
288
+ URL: &urlCopy,
289
}
290
291
// populate the replacer just enough for our tests