From f0bcffec8b14fb2294ba40f96e7c7884e9f53749 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Fri, 14 Jul 2023 11:55:29 +0300 Subject: [PATCH] [#2914] register the eagerRequestDataCache middleware only for the api grroup to avoid conflicts with custom routes --- apis/base.go | 6 +-- apis/base_test.go | 106 ++++++++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 46 deletions(-) diff --git a/apis/base.go b/apis/base.go index c2b9a225..7857b102 100644 --- a/apis/base.go +++ b/apis/base.go @@ -104,7 +104,7 @@ func InitApi(app core.App) (*echo.Echo, error) { bindStaticAdminUI(app, e) // default routes - api := e.Group("/api") + api := e.Group("/api", eagerRequestDataCache(app)) bindSettingsApi(app, api) bindAdminApi(app, api) bindCollectionApi(app, api) @@ -126,10 +126,6 @@ func InitApi(app core.App) (*echo.Echo, error) { return nil, err } - // note: it is after the OnBeforeServe hook to ensure that the implicit - // cache is after any user custom defined middlewares - e.Use(eagerRequestDataCache(app)) - // catch all any route api.Any("/*", func(c echo.Context) error { return echo.ErrNotFound diff --git a/apis/base_test.go b/apis/base_test.go index ee830ec6..087e258b 100644 --- a/apis/base_test.go +++ b/apis/base_test.go @@ -214,15 +214,16 @@ func TestRemoveTrailingSlashMiddleware(t *testing.T) { } func TestEagerRequestDataCache(t *testing.T) { + scenarios := []tests.ApiScenario{ { - Name: "[UNKNOWN] unsupported eager cached request method", - Method: "UNKNOWN", + Name: "custom non-api group route", + Method: "POST", Url: "/custom", Body: strings.NewReader(`{"name":"test123"}`), BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { e.AddRoute(echo.Route{ - Method: "UNKNOWN", + Method: "POST", Path: "/custom", Handler: func(c echo.Context) error { data := &struct { @@ -240,52 +241,75 @@ func TestEagerRequestDataCache(t *testing.T) { t.Fatalf("Expected empty request data body, got, %v", r.Data) } - return c.String(200, data.Name) + return c.NoContent(200) }, }) }, - ExpectedStatus: 200, - ExpectedContent: []string{"test123"}, + ExpectedStatus: 200, }, - } + { + Name: "api group route with unsupported eager cache request method", + Method: "GET", + Url: "/api/admins", + Body: strings.NewReader(`{"name":"test123"}`), + BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { + e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + next(c) - // supported eager cache request methods - supportedMethods := []string{"POST", "PUT", "PATCH", "DELETE"} - for _, m := range supportedMethods { - scenarios = append( - scenarios, - tests.ApiScenario{ - Name: fmt.Sprintf("[%s] valid cached json body request", m), - Method: http.MethodPost, - Url: "/custom", - Body: strings.NewReader(`{"name":"test123"}`), - BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { - e.AddRoute(echo.Route{ - Method: http.MethodPost, - Path: "/custom", - Handler: func(c echo.Context) error { - data := &struct { - Name string `json:"name"` - }{} + // ensure that the body is always read at least once + // (bind errors due to eof are not important) + data := &struct { + Name string `json:"name"` + }{} + c.Bind(data) - if err := c.Bind(data); err != nil { - return err - } + // since the unknown method is not eager cache support + // it should fail reading the json body twice + r := apis.RequestData(c) + if v := cast.ToString(r.Data["name"]); v != "" { + t.Fatalf("Expected empty request data body, got, %v", r.Data) + } - // try to read the body again - r := apis.RequestData(c) - if v := cast.ToString(r.Data["name"]); v != "test123" { - t.Fatalf("Expected request data with name %q, got, %q", "test123", v) - } - - return c.String(200, data.Name) - }, - }) - }, - ExpectedStatus: 200, - ExpectedContent: []string{"test123"}, + return nil + } + }) }, - ) + ExpectedStatus: 200, + }, + { + Name: "api group route with supported eager cache request method", + Method: "POST", + Url: "/api/admins", + RequestHeaders: map[string]string{ + "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8", + }, + Body: strings.NewReader(`{"name":"test123"}`), + BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) { + e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + next(c) + + // ensure that the body is always read at least once + // (bind errors due to eof are not important) + data := &struct { + Name string `json:"name"` + }{} + c.Bind(data) + + // try to read the body again + r := apis.RequestData(c) + fmt.Println(r) + if v := cast.ToString(r.Data["name"]); v != "test123" { + t.Fatalf("Expected request data with name %q, got, %q", "test123", v) + } + + return nil + } + }) + }, + ExpectedStatus: 200, + }, } for _, scenario := range scenarios {