1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-28 08:38:39 +02:00
echo/middleware/redirect.go
orangain ef82f3e034 Avoid redirect loop in HTTPSRedirect middleware (#1058)
In HTTPSRedirect and similar middlewares, determining if redirection is
needed using `c.IsTLS()` causes redirect loop when an application is running
behind a TLS termination proxy, e.g. AWS ELB.

Instead, I believe, redirection should be determined by
`c.Scheme() != "https"`. This works well even behind a TLS termination proxy.
2018-02-02 07:31:07 -08:00

154 lines
4.5 KiB
Go

package middleware
import (
"net/http"
"github.com/labstack/echo"
)
// RedirectConfig defines the config for Redirect middleware.
type RedirectConfig struct {
// Skipper defines a function to skip middleware.
Skipper
// Status code to be used when redirecting the request.
// Optional. Default value http.StatusMovedPermanently.
Code int `yaml:"code"`
}
// redirectLogic represents a function that given a scheme, host and uri
// can both: 1) determine if redirect is needed (will set ok accordingly) and
// 2) return the appropriate redirect url.
type redirectLogic func(scheme, host, uri string) (ok bool, url string)
const www = "www"
// DefaultRedirectConfig is the default Redirect middleware config.
var DefaultRedirectConfig = RedirectConfig{
Skipper: DefaultSkipper,
Code: http.StatusMovedPermanently,
}
// HTTPSRedirect redirects http requests to https.
// For example, http://labstack.com will be redirect to https://labstack.com.
//
// Usage `Echo#Pre(HTTPSRedirect())`
func HTTPSRedirect() echo.MiddlewareFunc {
return HTTPSRedirectWithConfig(DefaultRedirectConfig)
}
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `HTTPSRedirect()`.
func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = scheme != "https"; ok {
url = "https://" + host + uri
}
return
})
}
// HTTPSWWWRedirect redirects http requests to https www.
// For example, http://labstack.com will be redirect to https://www.labstack.com.
//
// Usage `Echo#Pre(HTTPSWWWRedirect())`
func HTTPSWWWRedirect() echo.MiddlewareFunc {
return HTTPSWWWRedirectWithConfig(DefaultRedirectConfig)
}
// HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `HTTPSWWWRedirect()`.
func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = scheme != "https" && host[:3] != www; ok {
url = "https://www." + host + uri
}
return
})
}
// HTTPSNonWWWRedirect redirects http requests to https non www.
// For example, http://www.labstack.com will be redirect to https://labstack.com.
//
// Usage `Echo#Pre(HTTPSNonWWWRedirect())`
func HTTPSNonWWWRedirect() echo.MiddlewareFunc {
return HTTPSNonWWWRedirectWithConfig(DefaultRedirectConfig)
}
// HTTPSNonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `HTTPSNonWWWRedirect()`.
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = scheme != "https"; ok {
if host[:3] == www {
host = host[4:]
}
url = "https://" + host + uri
}
return
})
}
// WWWRedirect redirects non www requests to www.
// For example, http://labstack.com will be redirect to http://www.labstack.com.
//
// Usage `Echo#Pre(WWWRedirect())`
func WWWRedirect() echo.MiddlewareFunc {
return WWWRedirectWithConfig(DefaultRedirectConfig)
}
// WWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `WWWRedirect()`.
func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = host[:3] != www; ok {
url = scheme + "://www." + host + uri
}
return
})
}
// NonWWWRedirect redirects www requests to non www.
// For example, http://www.labstack.com will be redirect to http://labstack.com.
//
// Usage `Echo#Pre(NonWWWRedirect())`
func NonWWWRedirect() echo.MiddlewareFunc {
return NonWWWRedirectWithConfig(DefaultRedirectConfig)
}
// NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `NonWWWRedirect()`.
func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = host[:3] == www; ok {
url = scheme + "://" + host[4:] + uri
}
return
})
}
func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc {
if config.Skipper == nil {
config.Skipper = DefaultTrailingSlashConfig.Skipper
}
if config.Code == 0 {
config.Code = DefaultRedirectConfig.Code
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if config.Skipper(c) {
return next(c)
}
req, scheme := c.Request(), c.Scheme()
host := req.Host
if ok, url := cb(scheme, host, req.RequestURI); ok {
return c.Redirect(config.Code, url)
}
return next(c)
}
}
}