aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/server.go
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2021-06-09 07:43:57 -0400
committerFilippo Valsorda <filippo@golang.org>2021-06-09 16:59:02 +0000
commite4e7807d240eb62e1d4a73eec2706975c8cc847b (patch)
tree6e6a0978ddc193e966ee62027c916ea346cdb62c /src/net/http/server.go
parentec3026d032be065fb26c5826b9abb7b6b806d7ef (diff)
downloadgo-e4e7807d240eb62e1d4a73eec2706975c8cc847b.tar.xz
net/http: add AllowQuerySemicolons
Fixes #45973 Change-Id: I6cbe05f5d1d3c324900c74314b0ea0e12524d7f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/326309 Run-TryBot: Filippo Valsorda <filippo@golang.org> Reviewed-by: Katie Hockman <katie@golang.org> Trust: Katie Hockman <katie@golang.org> Trust: Filippo Valsorda <filippo@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/net/http/server.go')
-rw-r--r--src/net/http/server.go45
1 files changed, 41 insertions, 4 deletions
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 8a1847e67a..50fab4520d 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -2862,12 +2862,49 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
- handler.ServeHTTP(rw, req)
+
if req.URL != nil && strings.Contains(req.URL.RawQuery, ";") {
- // TODO(filippo): update this not to log if the special
- // semicolon handler was called.
- sh.srv.logf("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192")
+ var allowQuerySemicolonsInUse int32
+ req = req.WithContext(context.WithValue(req.Context(), silenceSemWarnContextKey, func() {
+ atomic.StoreInt32(&allowQuerySemicolonsInUse, 1)
+ }))
+ defer func() {
+ if atomic.LoadInt32(&allowQuerySemicolonsInUse) == 0 {
+ sh.srv.logf("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192")
+ }
+ }()
}
+
+ handler.ServeHTTP(rw, req)
+}
+
+var silenceSemWarnContextKey = &contextKey{"silence-semicolons"}
+
+// AllowQuerySemicolons returns a handler that serves requests by converting any
+// unescaped semicolons in the URL query to ampersands, and invoking the handler h.
+//
+// This restores the pre-Go 1.17 behavior of splitting query parameters on both
+// semicolons and ampersands. (See golang.org/issue/25192). Note that this
+// behavior doesn't match that of many proxies, and the mismatch can lead to
+// security issues.
+//
+// AllowQuerySemicolons should be invoked before Request.ParseForm is called.
+func AllowQuerySemicolons(h Handler) Handler {
+ return HandlerFunc(func(w ResponseWriter, r *Request) {
+ if silenceSemicolonsWarning, ok := r.Context().Value(silenceSemWarnContextKey).(func()); ok {
+ silenceSemicolonsWarning()
+ }
+ if strings.Contains(r.URL.RawQuery, ";") {
+ r2 := new(Request)
+ *r2 = *r
+ r2.URL = new(url.URL)
+ *r2.URL = *r.URL
+ r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&")
+ h.ServeHTTP(w, r2)
+ } else {
+ h.ServeHTTP(w, r)
+ }
+ })
}
// ListenAndServe listens on the TCP network address srv.Addr and then