mirror of
https://github.com/labstack/echo.git
synced 2025-06-27 00:51:02 +02:00
This commit is contained in:
@ -2,6 +2,7 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -40,11 +41,11 @@ func HTTPSRedirect() echo.MiddlewareFunc {
|
|||||||
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||||
// See `HTTPSRedirect()`.
|
// See `HTTPSRedirect()`.
|
||||||
func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
||||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
return redirect(config, func(scheme, host, uri string) (bool, string) {
|
||||||
if ok = scheme != "https"; ok {
|
if scheme != "https" {
|
||||||
url = "https://" + host + uri
|
return true, "https://" + host + uri
|
||||||
}
|
}
|
||||||
return
|
return false, ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +60,11 @@ func HTTPSWWWRedirect() echo.MiddlewareFunc {
|
|||||||
// HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
// HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||||
// See `HTTPSWWWRedirect()`.
|
// See `HTTPSWWWRedirect()`.
|
||||||
func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
||||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
return redirect(config, func(scheme, host, uri string) (bool, string) {
|
||||||
if ok = scheme != "https" && host[:4] != www; ok {
|
if scheme != "https" && !strings.HasPrefix(host, www) {
|
||||||
url = "https://www." + host + uri
|
return true, "https://www." + host + uri
|
||||||
}
|
}
|
||||||
return
|
return false, ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,13 +80,11 @@ func HTTPSNonWWWRedirect() echo.MiddlewareFunc {
|
|||||||
// See `HTTPSNonWWWRedirect()`.
|
// See `HTTPSNonWWWRedirect()`.
|
||||||
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
||||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
||||||
if ok = scheme != "https"; ok {
|
if scheme != "https" {
|
||||||
if host[:4] == www {
|
host = strings.TrimPrefix(host, www)
|
||||||
host = host[4:]
|
return true, "https://" + host + uri
|
||||||
}
|
}
|
||||||
url = "https://" + host + uri
|
return false, ""
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +99,11 @@ func WWWRedirect() echo.MiddlewareFunc {
|
|||||||
// WWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
// WWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||||
// See `WWWRedirect()`.
|
// See `WWWRedirect()`.
|
||||||
func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
||||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
return redirect(config, func(scheme, host, uri string) (bool, string) {
|
||||||
if ok = host[:4] != www; ok {
|
if !strings.HasPrefix(host, www) {
|
||||||
url = scheme + "://www." + host + uri
|
return true, scheme + "://www." + host + uri
|
||||||
}
|
}
|
||||||
return
|
return false, ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,17 +118,17 @@ func NonWWWRedirect() echo.MiddlewareFunc {
|
|||||||
// NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
// NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
|
||||||
// See `NonWWWRedirect()`.
|
// See `NonWWWRedirect()`.
|
||||||
func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
|
||||||
return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
|
return redirect(config, func(scheme, host, uri string) (bool, string) {
|
||||||
if ok = host[:4] == www; ok {
|
if strings.HasPrefix(host, www) {
|
||||||
url = scheme + "://" + host[4:] + uri
|
return true, scheme + "://" + host[4:] + uri
|
||||||
}
|
}
|
||||||
return
|
return false, ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc {
|
func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc {
|
||||||
if config.Skipper == nil {
|
if config.Skipper == nil {
|
||||||
config.Skipper = DefaultTrailingSlashConfig.Skipper
|
config.Skipper = DefaultRedirectConfig.Skipper
|
||||||
}
|
}
|
||||||
if config.Code == 0 {
|
if config.Code == 0 {
|
||||||
config.Code = DefaultRedirectConfig.Code
|
config.Code = DefaultRedirectConfig.Code
|
||||||
|
@ -12,62 +12,253 @@ import (
|
|||||||
type middlewareGenerator func() echo.MiddlewareFunc
|
type middlewareGenerator func() echo.MiddlewareFunc
|
||||||
|
|
||||||
func TestRedirectHTTPSRedirect(t *testing.T) {
|
func TestRedirectHTTPSRedirect(t *testing.T) {
|
||||||
res := redirectTest(HTTPSRedirect, "labstack.com", nil)
|
var testCases = []struct {
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenHost: "labstack.com",
|
||||||
|
expectLocation: "https://labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "labstack.com",
|
||||||
|
whenHeader: map[string][]string{echo.HeaderXForwardedProto: {"https"}},
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusMovedPermanently, res.Code)
|
for _, tc := range testCases {
|
||||||
assert.Equal(t, "https://labstack.com/", res.Header().Get(echo.HeaderLocation))
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
}
|
res := redirectTest(HTTPSRedirect, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
func TestHTTPSRedirectBehindTLSTerminationProxy(t *testing.T) {
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
header := http.Header{}
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
header.Set(echo.HeaderXForwardedProto, "https")
|
})
|
||||||
res := redirectTest(HTTPSRedirect, "labstack.com", header)
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, res.Code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedirectHTTPSWWWRedirect(t *testing.T) {
|
func TestRedirectHTTPSWWWRedirect(t *testing.T) {
|
||||||
res := redirectTest(HTTPSWWWRedirect, "labstack.com", nil)
|
var testCases = []struct {
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenHost: "labstack.com",
|
||||||
|
expectLocation: "https://www.labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "a.com",
|
||||||
|
expectLocation: "https://www.a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "ip",
|
||||||
|
expectLocation: "https://www.ip/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "labstack.com",
|
||||||
|
whenHeader: map[string][]string{echo.HeaderXForwardedProto: {"https"}},
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusMovedPermanently, res.Code)
|
for _, tc := range testCases {
|
||||||
assert.Equal(t, "https://www.labstack.com/", res.Header().Get(echo.HeaderLocation))
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
}
|
res := redirectTest(HTTPSWWWRedirect, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
func TestRedirectHTTPSWWWRedirectBehindTLSTerminationProxy(t *testing.T) {
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
header := http.Header{}
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
header.Set(echo.HeaderXForwardedProto, "https")
|
})
|
||||||
res := redirectTest(HTTPSWWWRedirect, "labstack.com", header)
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, res.Code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedirectHTTPSNonWWWRedirect(t *testing.T) {
|
func TestRedirectHTTPSNonWWWRedirect(t *testing.T) {
|
||||||
res := redirectTest(HTTPSNonWWWRedirect, "www.labstack.com", nil)
|
var testCases = []struct {
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "https://labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "a.com",
|
||||||
|
expectLocation: "https://a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "ip",
|
||||||
|
expectLocation: "https://ip/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
whenHeader: map[string][]string{echo.HeaderXForwardedProto: {"https"}},
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusMovedPermanently, res.Code)
|
for _, tc := range testCases {
|
||||||
assert.Equal(t, "https://labstack.com/", res.Header().Get(echo.HeaderLocation))
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
}
|
res := redirectTest(HTTPSNonWWWRedirect, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
func TestRedirectHTTPSNonWWWRedirectBehindTLSTerminationProxy(t *testing.T) {
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
header := http.Header{}
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
header.Set(echo.HeaderXForwardedProto, "https")
|
})
|
||||||
res := redirectTest(HTTPSNonWWWRedirect, "www.labstack.com", header)
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, res.Code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedirectWWWRedirect(t *testing.T) {
|
func TestRedirectWWWRedirect(t *testing.T) {
|
||||||
res := redirectTest(WWWRedirect, "labstack.com", nil)
|
var testCases = []struct {
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenHost: "labstack.com",
|
||||||
|
expectLocation: "http://www.labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "a.com",
|
||||||
|
expectLocation: "http://www.a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "ip",
|
||||||
|
expectLocation: "http://www.ip/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "a.com",
|
||||||
|
whenHeader: map[string][]string{echo.HeaderXForwardedProto: {"https"}},
|
||||||
|
expectLocation: "https://www.a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "www.ip",
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusMovedPermanently, res.Code)
|
for _, tc := range testCases {
|
||||||
assert.Equal(t, "http://www.labstack.com/", res.Header().Get(echo.HeaderLocation))
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
|
res := redirectTest(WWWRedirect, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedirectNonWWWRedirect(t *testing.T) {
|
func TestRedirectNonWWWRedirect(t *testing.T) {
|
||||||
res := redirectTest(NonWWWRedirect, "www.labstack.com", nil)
|
var testCases = []struct {
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "http://labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "www.a.com",
|
||||||
|
expectLocation: "http://a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "www.a.com",
|
||||||
|
whenHeader: map[string][]string{echo.HeaderXForwardedProto: {"https"}},
|
||||||
|
expectLocation: "https://a.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenHost: "ip",
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(t, http.StatusMovedPermanently, res.Code)
|
for _, tc := range testCases {
|
||||||
assert.Equal(t, "http://labstack.com/", res.Header().Get(echo.HeaderLocation))
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
|
res := redirectTest(NonWWWRedirect, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNonWWWRedirectWithConfig(t *testing.T) {
|
||||||
|
var testCases = []struct {
|
||||||
|
name string
|
||||||
|
givenCode int
|
||||||
|
givenSkipFunc func(c echo.Context) bool
|
||||||
|
whenHost string
|
||||||
|
whenHeader http.Header
|
||||||
|
expectLocation string
|
||||||
|
expectStatusCode int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "usual redirect",
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "http://labstack.com/",
|
||||||
|
expectStatusCode: http.StatusMovedPermanently,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "redirect is skipped",
|
||||||
|
givenSkipFunc: func(c echo.Context) bool {
|
||||||
|
return true // skip always
|
||||||
|
},
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "",
|
||||||
|
expectStatusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "redirect with custom status code",
|
||||||
|
givenCode: http.StatusSeeOther,
|
||||||
|
whenHost: "www.labstack.com",
|
||||||
|
expectLocation: "http://labstack.com/",
|
||||||
|
expectStatusCode: http.StatusSeeOther,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.whenHost, func(t *testing.T) {
|
||||||
|
middleware := func() echo.MiddlewareFunc {
|
||||||
|
return NonWWWRedirectWithConfig(RedirectConfig{
|
||||||
|
Skipper: tc.givenSkipFunc,
|
||||||
|
Code: tc.givenCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
res := redirectTest(middleware, tc.whenHost, tc.whenHeader)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectStatusCode, res.Code)
|
||||||
|
assert.Equal(t, tc.expectLocation, res.Header().Get(echo.HeaderLocation))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func redirectTest(fn middlewareGenerator, host string, header http.Header) *httptest.ResponseRecorder {
|
func redirectTest(fn middlewareGenerator, host string, header http.Header) *httptest.ResponseRecorder {
|
||||||
|
Reference in New Issue
Block a user