package middleware import ( "bytes" "io" "net/http" "net/http/httptest" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" ) func TestBodyLimitConfig_ToMiddleware(t *testing.T) { e := echo.New() hw := []byte("Hello, World!") req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) h := func(c echo.Context) error { body, err := io.ReadAll(c.Request().Body) if err != nil { return err } return c.String(http.StatusOK, string(body)) } // Based on content length (within limit) mw, err := BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware() assert.NoError(t, err) err = mw(h)(c) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, hw, rec.Body.Bytes()) } // Based on content read (overlimit) mw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware() assert.NoError(t, err) he := mw(h)(c).(*echo.HTTPError) assert.Equal(t, http.StatusRequestEntityTooLarge, he.Code) // Based on content read (within limit) req = httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) req.ContentLength = -1 rec = httptest.NewRecorder() c = e.NewContext(req, rec) mw, err = BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware() assert.NoError(t, err) err = mw(h)(c) assert.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "Hello, World!", rec.Body.String()) // Based on content read (overlimit) req = httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) req.ContentLength = -1 rec = httptest.NewRecorder() c = e.NewContext(req, rec) mw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware() assert.NoError(t, err) he = mw(h)(c).(*echo.HTTPError) assert.Equal(t, http.StatusRequestEntityTooLarge, he.Code) } func TestBodyLimitReader(t *testing.T) { hw := []byte("Hello, World!") config := BodyLimitConfig{ Skipper: DefaultSkipper, LimitBytes: 2, } reader := &limitedReader{ BodyLimitConfig: config, reader: io.NopCloser(bytes.NewReader(hw)), } // read all should return ErrStatusRequestEntityTooLarge _, err := io.ReadAll(reader) he := err.(*echo.HTTPError) assert.Equal(t, http.StatusRequestEntityTooLarge, he.Code) // reset reader and read two bytes must succeed bt := make([]byte, 2) reader.Reset(io.NopCloser(bytes.NewReader(hw))) n, err := reader.Read(bt) assert.Equal(t, 2, n) assert.Equal(t, nil, err) } func TestBodyLimit_skipper(t *testing.T) { e := echo.New() h := func(c echo.Context) error { body, err := io.ReadAll(c.Request().Body) if err != nil { return err } return c.String(http.StatusOK, string(body)) } mw, err := BodyLimitConfig{ Skipper: func(c echo.Context) bool { return true }, LimitBytes: 2, }.ToMiddleware() assert.NoError(t, err) hw := []byte("Hello, World!") req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) err = mw(h)(c) assert.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, hw, rec.Body.Bytes()) } func TestBodyLimitWithConfig(t *testing.T) { e := echo.New() hw := []byte("Hello, World!") req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) h := func(c echo.Context) error { body, err := io.ReadAll(c.Request().Body) if err != nil { return err } return c.String(http.StatusOK, string(body)) } mw := BodyLimitWithConfig(BodyLimitConfig{LimitBytes: 2 * MB}) err := mw(h)(c) assert.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, hw, rec.Body.Bytes()) } func TestBodyLimit(t *testing.T) { e := echo.New() hw := []byte("Hello, World!") req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(hw)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) h := func(c echo.Context) error { body, err := io.ReadAll(c.Request().Body) if err != nil { return err } return c.String(http.StatusOK, string(body)) } mw := BodyLimit(2 * MB) err := mw(h)(c) assert.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, hw, rec.Body.Bytes()) }