Failing tests for access_control_allow_origin, upstream_fetch_timeout, upstream_max_response_size and downstream_timeout: their defaults, valid values from the file and the environment, invalid values aborting startup naming the key or variable and the value, the CORS middleware answering with the configured origin, and the server's write timeout coming from downstream_timeout. They do not compile until the settings exist. Model: opus-5-5
70 lines
2.0 KiB
Go
70 lines
2.0 KiB
Go
package server
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/pixa/internal/config"
|
|
)
|
|
|
|
// TestNewHTTPServerTimeouts verifies that the constructed http.Server
|
|
// carries every hardening timeout wired onto it, including the slowloris
|
|
// defense (ReadHeaderTimeout) and the keep-alive bound (IdleTimeout). This
|
|
// guards against a field being defined but never set on the server, so
|
|
// each assertion compares the server field to its constant, or, for
|
|
// WriteTimeout, to downstream_timeout from the config.
|
|
func TestNewHTTPServerTimeouts(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
s := &Server{config: &config.Config{
|
|
Port: 8080,
|
|
DownstreamTimeout: 45 * time.Second,
|
|
}}
|
|
|
|
srv := s.newHTTPServer()
|
|
|
|
fields := []struct {
|
|
name string
|
|
got time.Duration
|
|
want time.Duration
|
|
}{
|
|
{"ReadTimeout", srv.ReadTimeout, HTTPReadTimeout},
|
|
{"ReadHeaderTimeout", srv.ReadHeaderTimeout, HTTPReadHeaderTimeout},
|
|
{"WriteTimeout", srv.WriteTimeout, 45 * time.Second},
|
|
{"IdleTimeout", srv.IdleTimeout, HTTPIdleTimeout},
|
|
}
|
|
|
|
for _, f := range fields {
|
|
if f.got != f.want {
|
|
t.Errorf("%s = %v, want %v", f.name, f.got, f.want)
|
|
}
|
|
}
|
|
|
|
if srv.MaxHeaderBytes != HTTPMaxHeaderBytes {
|
|
t.Errorf("MaxHeaderBytes = %d, want %d",
|
|
srv.MaxHeaderBytes, HTTPMaxHeaderBytes)
|
|
}
|
|
|
|
if srv.Handler != s {
|
|
t.Error("Handler is not the server")
|
|
}
|
|
}
|
|
|
|
// TestHardeningTimeoutValues pins the intent behind the two new timeouts
|
|
// without hard-coding brittle exact durations: the header-read phase is
|
|
// bounded strictly shorter than the whole-request read (the slowloris
|
|
// dribble), and idle keep-alive connections are bounded rather than held
|
|
// open forever.
|
|
func TestHardeningTimeoutValues(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if HTTPReadHeaderTimeout <= 0 || HTTPReadHeaderTimeout > HTTPReadTimeout {
|
|
t.Errorf("ReadHeaderTimeout = %v, want positive and <= ReadTimeout %v",
|
|
HTTPReadHeaderTimeout, HTTPReadTimeout)
|
|
}
|
|
|
|
if HTTPIdleTimeout <= 0 {
|
|
t.Errorf("IdleTimeout = %v, want positive bound", HTTPIdleTimeout)
|
|
}
|
|
}
|