Make the HSTS max-age configurable with HSTS_MAX_AGE (closes #271)
check / check (push) Waiting to run
check / check (push) Waiting to run
HSTS_MAX_AGE, a Go duration, sets the max-age of the Strict-Transport-Security header. Unset, it is ten years (87600h); 0 sends no header at all. A negative value, or one that is not a whole number of seconds, stops startup like an unparseable one. includeSubDomains and preload stay in the header. The value is shown on /settings and in the startup log, and the README's HSTS section now says what each part of the header commits the operator to. Model: opus-5-5
This commit was merged in pull request #515.
This commit is contained in:
@@ -745,6 +745,70 @@ func TestNoCache_SetsHeaders(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
// --- SecurityHeaders Middleware Tests ---
|
||||
|
||||
// hstsHeaders serves one request through SecurityHeaders built over
|
||||
// a Config with the given HSTSMaxAge, and returns every
|
||||
// Strict-Transport-Security value on the response.
|
||||
func hstsHeaders(t *testing.T, maxAge time.Duration) []string {
|
||||
t.Helper()
|
||||
|
||||
cfg := &config.Config{HSTSMaxAge: maxAge}
|
||||
m := middlewaretest.New(
|
||||
t, slog.New(slog.DiscardHandler), cfg,
|
||||
newTestSessionManager(t, cfg),
|
||||
)
|
||||
|
||||
handler := m.SecurityHeaders()(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
},
|
||||
))
|
||||
|
||||
req := httptest.NewRequestWithContext(
|
||||
context.Background(), http.MethodGet, "/", nil,
|
||||
)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
return w.Header().Values("Strict-Transport-Security")
|
||||
}
|
||||
|
||||
func TestSecurityHeaders_HSTS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
maxAge time.Duration
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "default of ten years",
|
||||
maxAge: 87600 * time.Hour,
|
||||
expected: []string{"max-age=315360000; includeSubDomains; preload"},
|
||||
},
|
||||
{
|
||||
name: "custom value is sent in seconds",
|
||||
maxAge: 90 * time.Minute,
|
||||
expected: []string{"max-age=5400; includeSubDomains; preload"},
|
||||
},
|
||||
{
|
||||
name: "zero sends no header",
|
||||
maxAge: 0,
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Equal(t, tt.expected, hstsHeaders(t, tt.maxAge))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// --- MaxBodySize Middleware Tests ---
|
||||
|
||||
const testBodyLimit int64 = 64
|
||||
|
||||
Reference in New Issue
Block a user