Files
nexarch/internal/httpharden/harden_test.go
T

106 lines
3.1 KiB
Go

package httpharden
import (
"bufio"
"io"
"net"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestLimitBody_ContentLengthOverLimitIs413(t *testing.T) {
called := false
h := LimitBody(10, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true }))
req := httptest.NewRequest("POST", "/", strings.NewReader(strings.Repeat("a", 11)))
rec := httptest.NewRecorder()
h.ServeHTTP(rec, req)
if rec.Code != http.StatusRequestEntityTooLarge || called {
t.Fatalf("code=%d called=%v", rec.Code, called)
}
}
func TestLimitBody_ChunkedOverLimitFailsRead(t *testing.T) {
var readErr error
h := LimitBody(10, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, readErr = io.ReadAll(r.Body)
}))
req := httptest.NewRequest("POST", "/", strings.NewReader(strings.Repeat("a", 50)))
req.ContentLength = -1
h.ServeHTTP(httptest.NewRecorder(), req)
if readErr == nil {
t.Fatal("lesen ueber dem Limit muss fehlschlagen")
}
}
func TestLimitBody_UnderLimitPasses(t *testing.T) {
var got string
h := LimitBody(10, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, _ := io.ReadAll(r.Body)
got = string(b)
}))
h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("POST", "/", strings.NewReader("abc")))
if got != "abc" {
t.Fatalf("got %q", got)
}
}
func TestNewServer_DefaultsAndStreaming(t *testing.T) {
s := NewServer(":0", nil, Options{})
if s.ReadHeaderTimeout == 0 || s.ReadTimeout == 0 || s.WriteTimeout == 0 || s.IdleTimeout == 0 {
t.Fatalf("Timeouts muessen gesetzt sein: %+v", s)
}
st := NewServer(":0", nil, Options{StreamingBodies: true, StreamingResponses: true})
if st.ReadTimeout != 0 || st.WriteTimeout != 0 || st.ReadHeaderTimeout == 0 || st.IdleTimeout == 0 {
t.Fatalf("Streaming: nur Lese-/Schreib-Gesamtzeit 0: %+v", st)
}
}
func TestNewServer_EnvOverride(t *testing.T) {
t.Setenv(EnvReadHeaderTimeout, "3")
if got := NewServer(":0", nil, Options{}).ReadHeaderTimeout; got != 3*time.Second {
t.Fatalf("got %v", got)
}
}
func TestMaxBodyBytes_EnvOverride(t *testing.T) {
if MaxBodyBytes() != DefaultMaxBodyBytes {
t.Fatal("Standard")
}
t.Setenv(EnvMaxBodyBytes, "2048")
if MaxBodyBytes() != 2048 {
t.Fatal("Env")
}
}
// Slowloris: Verbindung sendet unvollstaendige Header, der Server trennt nach ReadHeaderTimeout.
func TestSlowHeadersAreClosed(t *testing.T) {
t.Setenv(EnvReadHeaderTimeout, "1")
srv := NewServer("127.0.0.1:0", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), Options{})
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
go srv.Serve(ln)
defer srv.Close()
conn, err := net.Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
if _, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: x\r\nX-Slow: a")); err != nil {
t.Fatal(err)
}
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
start := time.Now()
_, err = bufio.NewReader(conn).ReadByte()
if err == nil {
t.Log("Server antwortete (z. B. 408)")
}
if time.Since(start) > 4*time.Second {
t.Fatalf("Verbindung wurde nicht nach dem Header-Timeout beendet (%v)", time.Since(start))
}
}