package surf import ( "errors" "io" "net/http" "net/http/httptest" "strings" "testing" "git.golem15.com/golem15/summercms/backpack" "git.golem15.com/golem15/summercms/pact" "git.golem15.com/golem15/summercms/party" ) func TestBodyLimitDefaultRejectsOversizedBody(t *testing.T) { cfg := writeHTTPConfig(t, ` body_limits: default_bytes: 32 upload_bytes: 64 `) p := bodyEchoPlugin{id: "golem15.demo"} h, err := Assemble(backpack.New(cfg), []party.Plugin{p}) if err != nil { t.Fatal(err) } rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/echo", strings.NewReader(strings.Repeat("a", 64))) h.ServeHTTP(rec, req) if rec.Code != http.StatusRequestEntityTooLarge { t.Fatalf("status = %d body=%q (want 413 from MaxBytesReader)", rec.Code, rec.Body.String()) } rec = httptest.NewRecorder() req = httptest.NewRequest(http.MethodPost, "/echo", strings.NewReader("ok")) h.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("small body status = %d", rec.Code) } } func TestBodyLimitRawExempt(t *testing.T) { cfg := writeHTTPConfig(t, ` body_limits: default_bytes: 8 upload_bytes: 8 `) p := bodyEchoPlugin{id: "golem15.demo", raw: true} h, err := Assemble(backpack.New(cfg), []party.Plugin{p}) if err != nil { t.Fatal(err) } rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/echo", strings.NewReader(strings.Repeat("a", 64))) h.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("raw route should not apply default body limit, status = %d", rec.Code) } } func TestBodyLimitOverride(t *testing.T) { cfg := writeHTTPConfig(t, ` body_limits: default_bytes: 8 upload_bytes: 64 `) p := bodyEchoPlugin{id: "golem15.demo", extra: []string{"body.limit:64"}} h, err := Assemble(backpack.New(cfg), []party.Plugin{p}) if err != nil { t.Fatal(err) } rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/echo", strings.NewReader(strings.Repeat("a", 32))) h.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("override should allow 32 bytes, status = %d", rec.Code) } } func TestBodyLimitLoadsConfigValues(t *testing.T) { cfg := writeHTTPConfig(t, ` body_limits: default_bytes: 8388608 upload_bytes: 2097152 `) r, err := BuildRouter(backpack.New(cfg), nil) if err != nil { t.Fatal(err) } if r.defaultBytes != 8388608 || r.uploadBytes != 2097152 { t.Fatalf("limits = %d / %d", r.defaultBytes, r.uploadBytes) } } type bodyEchoPlugin struct { id string raw bool extra []string } func (p bodyEchoPlugin) ID() string { return p.id } func (p bodyEchoPlugin) Requires() []string { return nil } func (p bodyEchoPlugin) Register(*backpack.App) error { return nil } func (p bodyEchoPlugin) Boot(*backpack.App) error { return nil } func (p bodyEchoPlugin) Routes(r pact.Router) error { h := func(w http.ResponseWriter, req *http.Request) { _, err := io.Copy(io.Discard, req.Body) if err != nil { var maxErr *http.MaxBytesError if errors.As(err, &maxErr) { w.WriteHeader(http.StatusRequestEntityTooLarge) return } w.WriteHeader(http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) } open := r.Group if p.raw { open = r.GroupRaw } open("/", Use(p.extra...), func(g pact.Router) { g.Post("/echo", h) }) return nil }