diff --git a/pkg/server/interfaces.go b/pkg/server/interfaces.go index 633c394..6aeba53 100644 --- a/pkg/server/interfaces.go +++ b/pkg/server/interfaces.go @@ -19,6 +19,10 @@ type Config struct { // GZIP compression support GZIP bool + // HTTP2 enables HTTP/2 with the Extended CONNECT protocol (RFC 8441) for WebSocket support. + // Requires TLS; pair with SSLCert/SSLKey, SelfSignedSSL, or AutoTLS. + HTTP2 bool + // TLS/HTTPS configuration options (mutually exclusive) // Option 1: Provide certificate and key files directly SSLCert string diff --git a/pkg/server/manager.go b/pkg/server/manager.go index 61f16dc..f8c69ce 100644 --- a/pkg/server/manager.go +++ b/pkg/server/manager.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "os/signal" + "strings" "sync" "sync/atomic" "syscall" @@ -461,15 +462,34 @@ func newInstance(cfg Config) (*serverInstance, error) { } // Create gracefulServer + httpServer := &http.Server{ + Addr: addr, + Handler: handler, + ReadTimeout: cfg.ReadTimeout, + WriteTimeout: cfg.WriteTimeout, + IdleTimeout: cfg.IdleTimeout, + TLSConfig: tlsConfig, + } + + // Enable HTTP/2 with Extended CONNECT (RFC 8441) for WebSocket-over-H2 support. + // The GODEBUG=http2xconnect=1 flag is read by net/http's init(); setting it here + // ensures it propagates to subprocesses and any future process restarts. + // For the current process, set GODEBUG=http2xconnect=1 in the environment before launch. + if cfg.HTTP2 { + if existing := os.Getenv("GODEBUG"); !strings.Contains(existing, "http2xconnect=1") { + if existing == "" { + os.Setenv("GODEBUG", "http2xconnect=1") + } else { + os.Setenv("GODEBUG", existing+",http2xconnect=1") + } + } + if httpServer.HTTP2 == nil { + httpServer.HTTP2 = &http.HTTP2Config{} + } + } + gracefulSrv := &gracefulServer{ - server: &http.Server{ - Addr: addr, - Handler: handler, - ReadTimeout: cfg.ReadTimeout, - WriteTimeout: cfg.WriteTimeout, - IdleTimeout: cfg.IdleTimeout, - TLSConfig: tlsConfig, - }, + server: httpServer, shutdownTimeout: cfg.ShutdownTimeout, drainTimeout: cfg.DrainTimeout, shutdownComplete: make(chan struct{}),