diff options
| author | Filippo Valsorda <filippo@golang.org> | 2021-06-09 07:43:57 -0400 |
|---|---|---|
| committer | Filippo Valsorda <filippo@golang.org> | 2021-06-09 16:59:02 +0000 |
| commit | e4e7807d240eb62e1d4a73eec2706975c8cc847b (patch) | |
| tree | 6e6a0978ddc193e966ee62027c916ea346cdb62c /src/net/http/server.go | |
| parent | ec3026d032be065fb26c5826b9abb7b6b806d7ef (diff) | |
| download | go-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.go | 45 |
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 |
