diff --git a/cmd/secheaders-devserver/main.go b/cmd/secheaders-devserver/main.go
new file mode 100644
index 0000000..bb699a6
--- /dev/null
+++ b/cmd/secheaders-devserver/main.go
@@ -0,0 +1,40 @@
+// secheaders-devserver dient der manuellen/e2e-Verifikation von API-08
+// (Pruefung 2: CSP blockiert Inline-Script) mit einem echten Browser.
+// Zwei Pfade: /protected (mit Middleware) und /unprotected (ohne) — beide
+// liefern dieselbe Seite mit einem Inline-Script, das ein DOM-Element
+// aendert. Ein echter Browser zeigt den Unterschied.
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "gitea.perlbach24.de/scripte/nexarch/internal/secheaders"
+)
+
+const page = `
+
+BLOCKED
+
+`
+
+func servePage(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ _, _ = w.Write([]byte(page))
+}
+
+func main() {
+ cfg := secheaders.DefaultConfig()
+ mux := http.NewServeMux()
+ // SetHeaders statt Middleware: dieser lokale Demo-Server laeuft ohne
+ // TLS-Terminierung, der HTTPS-Redirect-Teil von Middleware wuerde hier
+ // in eine Endlosschleife fuehren (siehe secheaders.go-Dokumentation).
+ mux.HandleFunc("/protected", func(w http.ResponseWriter, r *http.Request) {
+ secheaders.SetHeaders(cfg, w)
+ servePage(w, r)
+ })
+ mux.HandleFunc("/unprotected", servePage)
+
+ log.Println("secheaders-devserver listening on :8086")
+ log.Fatal(http.ListenAndServe(":8086", mux))
+}
diff --git a/internal/secheaders/secheaders.go b/internal/secheaders/secheaders.go
index 4d91fb4..a15ebfd 100644
--- a/internal/secheaders/secheaders.go
+++ b/internal/secheaders/secheaders.go
@@ -83,18 +83,25 @@ func Middleware(cfg Config, next http.HandlerFunc) http.HandlerFunc {
return
}
- w.Header().Set("Content-Security-Policy", cfg.ContentSecurityPolicy)
- w.Header().Set("Strict-Transport-Security", cfg.hstsValue())
- w.Header().Set("X-Frame-Options", cfg.FrameOptions)
- w.Header().Set("Referrer-Policy", cfg.ReferrerPolicy)
- if cfg.ContentTypeNoSniff {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- }
-
+ SetHeaders(cfg, w)
next(w, r)
}
}
+// SetHeaders setzt die Baseline-Header direkt, OHNE die HTTPS-Redirect-
+// Pruefung von Middleware — nuetzlich fuer lokale Entwicklungs-/
+// Demo-Umgebungen ohne TLS-Terminierung (siehe cmd/secheaders-devserver)
+// und fuer Aufrufer, die den Redirect selbst schon anderweitig sicherstellen.
+func SetHeaders(cfg Config, w http.ResponseWriter) {
+ w.Header().Set("Content-Security-Policy", cfg.ContentSecurityPolicy)
+ w.Header().Set("Strict-Transport-Security", cfg.hstsValue())
+ w.Header().Set("X-Frame-Options", cfg.FrameOptions)
+ w.Header().Set("Referrer-Policy", cfg.ReferrerPolicy)
+ if cfg.ContentTypeNoSniff {
+ w.Header().Set("X-Content-Type-Options", "nosniff")
+ }
+}
+
// isSecure erkennt TLS direkt ODER ueber den ueblichen Reverse-Proxy-Header
// (X-Forwarded-Proto) — der Core-Dienst laeuft in der Praxis hinter einem
// TLS-terminierenden Proxy, sieht r.TLS also nie direkt gesetzt.