Encode query semicolons

Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
LandryBe 2023-06-15 18:20:06 +02:00 committed by GitHub
parent 6885e410f0
commit e62fe64ec9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 176 additions and 4 deletions

View file

@ -57,9 +57,10 @@ func (ep *EntryPoint) SetDefaults() {
// HTTPConfig is the HTTP configuration of an entry point.
type HTTPConfig struct {
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty" export:"true"`
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty" export:"true"`
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
EncodeQuerySemicolons bool `description:"Defines whether request query semicolons should be URLEncoded." json:"encodeQuerySemicolons,omitempty" toml:"encodeQuerySemicolons,omitempty" yaml:"encodeQuerySemicolons,omitempty"`
}
// HTTP2Config is the HTTP2 configuration of an entry point.

View file

@ -535,7 +535,11 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
return nil, err
}
handler = http.AllowQuerySemicolons(handler)
if configuration.HTTP.EncodeQuerySemicolons {
handler = encodeQuerySemicolons(handler)
} else {
handler = http.AllowQuerySemicolons(handler)
}
if withH2c {
handler = h2c.NewHandler(handler, &http2.Server{
@ -596,3 +600,23 @@ func (t *trackedConnection) Close() error {
t.tracker.RemoveConnection(t.WriteCloser)
return t.WriteCloser.Close()
}
// This function is inspired by http.AllowQuerySemicolons.
func encodeQuerySemicolons(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if strings.Contains(req.URL.RawQuery, ";") {
r2 := new(http.Request)
*r2 = *req
r2.URL = new(url.URL)
*r2.URL = *req.URL
r2.URL.RawQuery = strings.ReplaceAll(req.URL.RawQuery, ";", "%3B")
// Because the reverse proxy director is building query params from requestURI it needs to be updated as well.
r2.RequestURI = r2.URL.RequestURI()
h.ServeHTTP(rw, r2)
} else {
h.ServeHTTP(rw, req)
}
})
}

View file

@ -48,6 +48,7 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
outReq.URL.Path = u.Path
outReq.URL.RawPath = u.RawPath
// If a plugin/middleware adds semicolons in query params, they should be urlEncoded.
outReq.URL.RawQuery = strings.ReplaceAll(u.RawQuery, ";", "&")
outReq.RequestURI = "" // Outgoing request should not have RequestURI