-
Notifications
You must be signed in to change notification settings - Fork 0
/
http-redirect.go
91 lines (69 loc) · 2.23 KB
/
http-redirect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package nameshift
import (
"fmt"
"net"
"net/http"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"go.uber.org/zap"
)
func init() {
caddy.RegisterModule(Middleware{})
httpcaddyfile.RegisterHandlerDirective("redirect_if_cert_available", parseCaddyfile)
httpcaddyfile.RegisterDirectiveOrder("redirect_if_cert_available", httpcaddyfile.Before, "redir")
}
type Middleware struct {
logger *zap.Logger
}
func (Middleware) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.redirect_if_cert_available",
New: func() caddy.Module { return new(Middleware) },
}
}
func (h *Middleware) Provision(ctx caddy.Context) error {
h.logger = ctx.Logger(h)
return nil
}
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
handler := &Middleware{}
err := handler.UnmarshalCaddyfile(h.Dispenser)
return handler, err
}
func (h *Middleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return nil
}
func hostOnly(hostport string) string {
host, _, err := net.SplitHostPort(hostport)
if err != nil {
return hostport // OK; probably had no port to begin with
}
return host
}
func (h *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
requestHost := hostOnly(r.Host)
exists := HasCertificate(requestHost)
h.logger.Debug(fmt.Sprintf("Checking certificate for %s: %t", r.Host, exists))
if exists {
h.logger.Debug(fmt.Sprintf("Certificate found for %s", r.Host))
toURL := "https://"
// since we redirect to the standard HTTPS port, we
// do not need to include it in the redirect URL
toURL += requestHost
toURL += r.URL.RequestURI()
// get rid of this disgusting unencrypted HTTP connection 🤢
w.Header().Set("Connection", "close")
http.Redirect(w, r, toURL, http.StatusMovedPermanently)
} else {
h.logger.Debug(fmt.Sprintf("No certificate found for %s", r.Host))
return next.ServeHTTP(w, r)
}
return nil
}
var (
_ caddy.Provisioner = (*Middleware)(nil)
_ caddyfile.Unmarshaler = (*Middleware)(nil)
_ caddyhttp.MiddlewareHandler = (*Middleware)(nil)
)