Fix SSL redirect middleware to match NGINX behavior
This commit is contained in:
parent
7314f7ddc9
commit
d6b127ba91
10 changed files with 70 additions and 33 deletions
|
|
@ -18,30 +18,32 @@ const typeName = "Redirect"
|
|||
var uriRegexp = regexp.MustCompile(`^(https?):\/\/(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`)
|
||||
|
||||
type redirect struct {
|
||||
next http.Handler
|
||||
regex *regexp.Regexp
|
||||
replacement string
|
||||
permanent bool
|
||||
errHandler utils.ErrorHandler
|
||||
name string
|
||||
rawURL func(*http.Request) string
|
||||
next http.Handler
|
||||
regex *regexp.Regexp
|
||||
replacement string
|
||||
permanent bool
|
||||
forcePermanentRedirect bool
|
||||
errHandler utils.ErrorHandler
|
||||
name string
|
||||
rawURL func(*http.Request) string
|
||||
}
|
||||
|
||||
// New creates a Redirect middleware.
|
||||
func newRedirect(next http.Handler, regex, replacement string, permanent bool, rawURL func(*http.Request) string, name string) (http.Handler, error) {
|
||||
func newRedirect(next http.Handler, regex, replacement string, permanent bool, forcePermanentRedirect bool, rawURL func(*http.Request) string, name string) (http.Handler, error) {
|
||||
re, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &redirect{
|
||||
regex: re,
|
||||
replacement: replacement,
|
||||
permanent: permanent,
|
||||
errHandler: utils.DefaultHandler,
|
||||
next: next,
|
||||
name: name,
|
||||
rawURL: rawURL,
|
||||
regex: re,
|
||||
replacement: replacement,
|
||||
permanent: permanent,
|
||||
forcePermanentRedirect: forcePermanentRedirect,
|
||||
errHandler: utils.DefaultHandler,
|
||||
next: next,
|
||||
name: name,
|
||||
rawURL: rawURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +71,7 @@ func (r *redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
if newURL != oldURL {
|
||||
handler := &moveHandler{location: parsedURL, permanent: r.permanent}
|
||||
handler := &moveHandler{location: parsedURL, permanent: r.permanent, forcePermanentRedirect: r.forcePermanentRedirect}
|
||||
handler.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
|
@ -82,8 +84,9 @@ func (r *redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
type moveHandler struct {
|
||||
location *url.URL
|
||||
permanent bool
|
||||
location *url.URL
|
||||
permanent bool
|
||||
forcePermanentRedirect bool
|
||||
}
|
||||
|
||||
func (m *moveHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
|
|
@ -100,6 +103,11 @@ func (m *moveHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
status = http.StatusPermanentRedirect
|
||||
}
|
||||
}
|
||||
|
||||
if m.forcePermanentRedirect {
|
||||
status = http.StatusPermanentRedirect
|
||||
}
|
||||
|
||||
rw.WriteHeader(status)
|
||||
_, err := rw.Write([]byte(http.StatusText(status)))
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func NewRedirectRegex(ctx context.Context, next http.Handler, conf dynamic.Redir
|
|||
logger.Debug().Msg("Creating middleware")
|
||||
logger.Debug().Msgf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement)
|
||||
|
||||
return newRedirect(next, conf.Regex, conf.Replacement, conf.Permanent, rawURL, name)
|
||||
return newRedirect(next, conf.Regex, conf.Replacement, conf.Permanent, false, rawURL, name)
|
||||
}
|
||||
|
||||
func rawURL(req *http.Request) string {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi
|
|||
|
||||
rs := &redirectScheme{name: name}
|
||||
|
||||
handler, err := newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, rs.clientRequestURL, name)
|
||||
handler, err := newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, conf.ForcePermanentRedirect, rs.clientRequestURL, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,27 @@ func TestRedirectSchemeHandler(t *testing.T) {
|
|||
expectedURL: "https://foo:8443",
|
||||
expectedStatus: http.StatusMovedPermanently,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS with explicit 308 status code",
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
ForcePermanentRedirect: true,
|
||||
},
|
||||
url: "http://foo",
|
||||
expectedURL: "https://foo",
|
||||
expectedStatus: http.StatusPermanentRedirect,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS with explicit 308 status code for GET request",
|
||||
method: http.MethodGet,
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
ForcePermanentRedirect: true,
|
||||
},
|
||||
url: "http://foo",
|
||||
expectedURL: "https://foo",
|
||||
expectedStatus: http.StatusPermanentRedirect,
|
||||
},
|
||||
{
|
||||
desc: "to HTTP 80",
|
||||
config: dynamic.RedirectScheme{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue