diff --git a/safeweb/http.go b/safeweb/http.go index 9130b42d3..14c61336a 100644 --- a/safeweb/http.go +++ b/safeweb/http.go @@ -144,6 +144,12 @@ type Config struct { // BrowserMux when SecureContext is true. // If empty, it defaults to max-age of 1 year. StrictTransportSecurityOptions string + + // HTTPServer, if specified, is the underlying http.Server that safeweb will + // use to serve requests. If nil, a new http.Server will be created. + // Do not use the Handler field of http.Server, as it will be ignored. + // Instead, set your handlers using APIMux and BrowserMux. + HTTPServer *http.Server } func (c *Config) setDefaults() error { @@ -203,7 +209,11 @@ func NewServer(config Config) (*Server, error) { if config.CSPAllowInlineStyles { s.csp = defaultCSP + `; style-src 'self' 'unsafe-inline'` } - s.h = &http.Server{Handler: s} + s.h = cmp.Or(config.HTTPServer, &http.Server{}) + if s.h.Handler != nil { + return nil, fmt.Errorf("use safeweb.Config.APIMux and safeweb.Config.BrowserMux instead of http.Server.Handler") + } + s.h.Handler = s return s, nil } diff --git a/safeweb/http_test.go b/safeweb/http_test.go index 843da08aa..cec14b2b9 100644 --- a/safeweb/http_test.go +++ b/safeweb/http_test.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/gorilla/csrf" @@ -609,3 +610,26 @@ func TestStrictTransportSecurityOptions(t *testing.T) { }) } } + +func TestOverrideHTTPServer(t *testing.T) { + s, err := NewServer(Config{}) + if err != nil { + t.Fatalf("NewServer: %v", err) + } + if s.h.IdleTimeout != 0 { + t.Fatalf("got %v; want 0", s.h.IdleTimeout) + } + + c := http.Server{ + IdleTimeout: 10 * time.Second, + } + + s, err = NewServer(Config{HTTPServer: &c}) + if err != nil { + t.Fatalf("NewServer: %v", err) + } + + if s.h.IdleTimeout != c.IdleTimeout { + t.Fatalf("got %v; want %v", s.h.IdleTimeout, c.IdleTimeout) + } +}