-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.go
More file actions
92 lines (80 loc) · 2.92 KB
/
handler.go
File metadata and controls
92 lines (80 loc) · 2.92 KB
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
92
package hsts
import (
"bytes"
"net/http"
"strconv"
"time"
)
// Handler is a HTTP handler which will redirect any request served over HTTP over to HTTPS and apply a
// HSTS header.
type Handler struct {
next http.Handler
// MaxAge sets the duration that the HSTS is valid for.
MaxAge time.Duration
// HostOverride provides a host to the redirection URL in the case that the system is behind a load balancer
// which doesn't provide the X-Forwarded-Host HTTP header (e.g. an Amazon ELB).
HostOverride string
// Decides whether to accept the X-Forwarded-Proto header as proof of SSL.
AcceptXForwardedProtoHeader bool
// SendPreloadDirective sets whether the preload directive should be set. The directive allows browsers to
// confirm that the site should be added to a preload list. (see https://hstspreload.appspot.com/)
SendPreloadDirective bool
}
// NewHandler creates a new HSTS redirector, which will redirect any request served over HTTP over to HTTPS.
func NewHandler(next http.Handler) *Handler {
return &Handler{
next: next,
MaxAge: time.Hour * 24 * 400, // 126 days (minimum for inclusion in the Chrome HSTS list) // am changed it to 400 Days
AcceptXForwardedProtoHeader: true,
SendPreloadDirective: true, // changed it to true
}
}
func isHTTPS(r *http.Request, acceptXForwardedProtoHeader bool) bool {
// Added by common load balancers which do TLS offloading.
if acceptXForwardedProtoHeader && r.Header.Get("X-Forwarded-Proto") == "https" {
return true
}
// If the X-Forwarded-Proto was set upstream as HTTP, then the request came in without TLS.
if acceptXForwardedProtoHeader && r.Header.Get("X-Forwarded-Proto") == "http" {
return false
}
// Set by some middleware.
if r.URL.Scheme == "https" {
return true
}
// Set when the Go server is running HTTPS itself.
if r.TLS != nil && r.TLS.HandshakeComplete {
return true
}
return false
}
func createHeaderValue(maxAge time.Duration, sendPreloadDirective bool) string {
timeInSeconds := int(maxAge.Seconds())
if sendPreloadDirective {
return "max-age=" + strconv.Itoa(timeInSeconds) + "; includeSubDomains; preload"
}
return "max-age=" + strconv.Itoa(timeInSeconds) + "; includeSubDomains"
}
func createHeaderValueNew(maxAge time.Duration, sendPreloadDirective bool) string {
buf := bytes.NewBufferString("max-age=")
buf.WriteString(strconv.Itoa(int(maxAge.Seconds())))
buf.WriteString("; includeSubDomains")
if sendPreloadDirective {
buf.WriteString("; preload")
}
return buf.String()
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if isHTTPS(r, h.AcceptXForwardedProtoHeader) {
w.Header().Add("Strict-Transport-Security", createHeaderValue(h.MaxAge, h.SendPreloadDirective))
h.next.ServeHTTP(w, r)
} else {
if h.HostOverride != "" {
r.URL.Host = h.HostOverride
} else if !r.URL.IsAbs() {
r.URL.Host = r.Host
}
r.URL.Scheme = "https"
http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
}
}