fix: sanitize X-Forwarded-Proto header in RedirectScheme middleware
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
parent
e7baf44a2e
commit
29b8b6911e
2 changed files with 21 additions and 6 deletions
|
@ -18,6 +18,12 @@ const (
|
|||
xForwardedProto = "X-Forwarded-Proto"
|
||||
)
|
||||
|
||||
type redirectScheme struct {
|
||||
http.Handler
|
||||
|
||||
name string
|
||||
}
|
||||
|
||||
// NewRedirectScheme creates a new RedirectScheme middleware.
|
||||
func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) {
|
||||
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeSchemeName))
|
||||
|
@ -33,10 +39,19 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi
|
|||
port = ":" + conf.Port
|
||||
}
|
||||
|
||||
return newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, clientRequestURL, name)
|
||||
rs := &redirectScheme{name: name}
|
||||
|
||||
handler, err := newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, rs.clientRequestURL, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rs.Handler = handler
|
||||
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func clientRequestURL(req *http.Request) string {
|
||||
func (r *redirectScheme) clientRequestURL(req *http.Request) string {
|
||||
scheme := schemeHTTP
|
||||
host, port, err := net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
|
@ -71,12 +86,12 @@ func clientRequestURL(req *http.Request) string {
|
|||
// Given that we're in a middleware that is only used in the context of HTTP(s) requests,
|
||||
// the only possible valid schemes are one of "http" or "https", so we convert back to them.
|
||||
switch {
|
||||
case strings.EqualFold(xProto, "ws"):
|
||||
case strings.EqualFold(xProto, schemeHTTP), strings.EqualFold(xProto, "ws"):
|
||||
scheme = schemeHTTP
|
||||
case strings.EqualFold(xProto, "wss"):
|
||||
case strings.EqualFold(xProto, schemeHTTPS), strings.EqualFold(xProto, "wss"):
|
||||
scheme = schemeHTTPS
|
||||
default:
|
||||
scheme = xProto
|
||||
log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeSchemeName)).Debugf("invalid X-Forwarded-Proto: %s", xProto)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ func TestRedirectSchemeHandler(t *testing.T) {
|
|||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "bar",
|
||||
},
|
||||
expectedURL: "https://bar://foo",
|
||||
expectedURL: "https://foo",
|
||||
expectedStatus: http.StatusFound,
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue