80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"update_server/internal/config"
|
|
)
|
|
|
|
const contentSecurityPolicy = "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; style-src 'self'"
|
|
|
|
func securityHeaders(cfg config.Config) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
headers := w.Header()
|
|
headers.Set("Content-Security-Policy", contentSecurityPolicy)
|
|
headers.Set("Cross-Origin-Opener-Policy", "same-origin")
|
|
headers.Set("Cross-Origin-Resource-Policy", "same-origin")
|
|
headers.Set("Permissions-Policy", "camera=(), geolocation=(), microphone=()")
|
|
headers.Set("Referrer-Policy", "no-referrer")
|
|
headers.Set("X-Content-Type-Options", "nosniff")
|
|
headers.Set("X-Frame-Options", "DENY")
|
|
|
|
if cfg.SecureCookies {
|
|
headers.Set("Strict-Transport-Security", "max-age=31536000")
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
}
|
|
|
|
func adminResponseHeaders(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
applyNoStoreHeaders(w)
|
|
addVaryHeader(w, "Cookie")
|
|
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func apiResponseHeaders(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func protectedAPIResponseHeaders(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
applyNoStoreHeaders(w)
|
|
addVaryHeader(w, "Authorization")
|
|
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func applyNoStoreHeaders(w http.ResponseWriter) {
|
|
w.Header().Set("Cache-Control", "no-store, private, max-age=0")
|
|
w.Header().Set("Pragma", "no-cache")
|
|
w.Header().Set("Expires", "0")
|
|
}
|
|
|
|
func addVaryHeader(w http.ResponseWriter, value string) {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return
|
|
}
|
|
|
|
current := w.Header().Values("Vary")
|
|
for _, entry := range current {
|
|
for _, existing := range strings.Split(entry, ",") {
|
|
if strings.EqualFold(strings.TrimSpace(existing), value) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
w.Header().Add("Vary", value)
|
|
}
|