aboutsummaryrefslogtreecommitdiff
path: root/echo/middleware/www_redirect.go
diff options
context:
space:
mode:
Diffstat (limited to 'echo/middleware/www_redirect.go')
-rw-r--r--echo/middleware/www_redirect.go77
1 files changed, 77 insertions, 0 deletions
diff --git a/echo/middleware/www_redirect.go b/echo/middleware/www_redirect.go
new file mode 100644
index 0000000..905a5cf
--- /dev/null
+++ b/echo/middleware/www_redirect.go
@@ -0,0 +1,77 @@
1package middleware
2
3import (
4 "fmt"
5 "net"
6 "net/http"
7 "strings"
8
9 "github.com/labstack/echo/v4"
10 "github.com/labstack/echo/v4/middleware"
11)
12
13/*
14WWW Redirect Middleware
15
16This is a duplicate of existing functionality in Echo. This exists
17because we don't want to prefix www to a request that is an IP address
18only, only requests that use hostnames.
19*/
20
21type WWWRedirectConfig struct {
22 Skipper middleware.Skipper
23 Code int
24}
25
26var DefaultWWWRedirectConfig = WWWRedirectConfig{
27 Skipper: middleware.DefaultSkipper,
28 Code: http.StatusMovedPermanently,
29}
30
31func WWWRedirect() echo.MiddlewareFunc {
32 return WWWRedirectWithConfig(DefaultWWWRedirectConfig)
33}
34
35func WWWRedirectWithConfig(config WWWRedirectConfig) echo.MiddlewareFunc {
36 if config.Skipper == nil {
37 config.Skipper = DefaultWWWRedirectConfig.Skipper
38 }
39 if config.Code == 0 {
40 config.Code = DefaultWWWRedirectConfig.Code
41 }
42
43 return func(next echo.HandlerFunc) echo.HandlerFunc {
44 return func(c echo.Context) error {
45 req := c.Request()
46
47 if config.Skipper(c) || strings.HasPrefix(req.Host, "www.") {
48 return next(c)
49 }
50
51 host, _, err := net.SplitHostPort(req.Host)
52 if err != nil {
53 return echo.ErrBadRequest
54 }
55
56 // Never prefix an IP with www
57 //
58 // We have to parse the hostname for something that looks like an IP
59 // because the golang http server removes the header from the header
60 // map and there's no good way to unambiguously determine if this was
61 // a raw IP request or if a hostname was submitted.
62 //
63 // TLS connections could use the req.TLS.ServerName property which
64 // should have the correct hostname but there's no such thing for HTTP.
65 // Instead we just try to parse anything that makes it to this point
66 // because it should be a small one-time cost for a few requests.
67 if ip := net.ParseIP(host); ip != nil {
68 return next(c)
69 }
70
71 return c.Redirect(
72 config.Code,
73 fmt.Sprintf("https://www.%s%s", req.Host, req.RequestURI),
74 )
75 }
76 }
77}