@marcel91200 / caddy Mirror · read-only / commits / 693e9b52
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 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