diff --git a/modules/caddyhttp/requestbody/requestbody_test.go b/modules/caddyhttp/requestbody/requestbody_test.go new file mode 100644 index 000000000..40cbb4b62 --- /dev/null +++ b/modules/caddyhttp/requestbody/requestbody_test.go @@ -0,0 +1,134 @@ +package requestbody + +import ( + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/caddyserver/caddy/v2/modules/caddyhttp" +) + +func TestRequestBodyCaddyModule(t *testing.T) { + rb := RequestBody{} + info := rb.CaddyModule() + if info.ID != "http.handlers.request_body" { + t.Errorf("CaddyModule().ID = %v, want 'http.handlers.request_body'", info.ID) + } + if info.New == nil { + t.Fatal("CaddyModule().New is nil") + } +} + +func TestErrorWrapperMaxBytesError(t *testing.T) { + body := strings.NewReader("this body exceeds the limit") + w := httptest.NewRecorder() + limitedReader := http.MaxBytesReader(w, io.NopCloser(body), 5) + ew := errorWrapper{limitedReader} + + buf := make([]byte, 100) + totalRead := 0 + for { + n, err := ew.Read(buf[totalRead:]) + totalRead += n + if err != nil { + httpErr, ok := err.(caddyhttp.HandlerError) + if !ok { + t.Fatalf("error should be caddyhttp.HandlerError, got %T: %v", err, err) + } + if httpErr.StatusCode != http.StatusRequestEntityTooLarge { + t.Errorf("status code = %d, want %d", httpErr.StatusCode, http.StatusRequestEntityTooLarge) + } + break + } + } +} + +func TestErrorWrapperNormalRead(t *testing.T) { + body := strings.NewReader("hello") + w := httptest.NewRecorder() + limitedReader := http.MaxBytesReader(w, io.NopCloser(body), 1000) + ew := errorWrapper{limitedReader} + + buf := make([]byte, 100) + n, err := ew.Read(buf) + if err != nil { + t.Fatalf("Read() error: %v", err) + } + if string(buf[:n]) != "hello" { + t.Errorf("Read() = %q, want %q", string(buf[:n]), "hello") + } +} + +func TestServeHTTPMaxSize(t *testing.T) { + rb := RequestBody{MaxSize: 5} + body := io.NopCloser(strings.NewReader("this body is definitely longer than five bytes")) + r := httptest.NewRequest("POST", "/", body) + w := httptest.NewRecorder() + + var calledNext bool + nextHandler := caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { + calledNext = true + data, err := io.ReadAll(r.Body) + if err != nil { + return err + } + _ = data + return nil + }) + + err := rb.ServeHTTP(w, r, nextHandler) + if !calledNext { + t.Error("next handler should have been called") + } + if err == nil { + t.Error("expected error due to MaxSize exceeded") + } +} + +func TestServeHTTPNilBody(t *testing.T) { + rb := RequestBody{MaxSize: 100} + r := httptest.NewRequest("GET", "/", nil) + r.Body = nil + w := httptest.NewRecorder() + + var calledNext bool + nextHandler := caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { + calledNext = true + return nil + }) + + err := rb.ServeHTTP(w, r, nextHandler) + if err != nil { + t.Fatalf("ServeHTTP() error: %v", err) + } + if !calledNext { + t.Error("next handler should have been called") + } +} + +func TestServeHTTPZeroMaxSize(t *testing.T) { + rb := RequestBody{MaxSize: 0} + body := io.NopCloser(strings.NewReader("some body")) + r := httptest.NewRequest("POST", "/", body) + w := httptest.NewRecorder() + + var bodyContent string + nextHandler := caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { + data, err := io.ReadAll(r.Body) + if err != nil { + return err + } + bodyContent = string(data) + return nil + }) + + err := rb.ServeHTTP(w, r, nextHandler) + if err != nil { + t.Fatalf("ServeHTTP() error: %v", err) + } + if bodyContent != "some body" { + t.Errorf("body = %q, want %q", bodyContent, "some body") + } +}