diff --git a/api/middleware/middleware_test.go b/api/middleware/middleware_test.go index f605bbe20d..48ecab88ff 100644 --- a/api/middleware/middleware_test.go +++ b/api/middleware/middleware_test.go @@ -24,6 +24,7 @@ import ( "github.com/gin-gonic/gin" "github.com/pingcap/kvproto/pkg/keyspacepb" + cerrors "github.com/pingcap/ticdc/pkg/errors" "github.com/pingcap/ticdc/pkg/node" "github.com/pingcap/ticdc/pkg/pdutil" "github.com/pingcap/ticdc/pkg/server" @@ -205,6 +206,57 @@ func TestForwardToCoordinator(t *testing.T) { } } +func TestErrorHandleMiddleware(t *testing.T) { + gin.SetMode(gin.TestMode) + + cases := []struct { + name string + err error + wantStatus int + }{ + { + name: "no error returns 200", + err: nil, + wantStatus: http.StatusOK, + }, + { + name: "registered bad-request error returns 400", + err: cerrors.ErrAPIInvalidParam.GenWithStackByArgs("bad input"), + wantStatus: http.StatusBadRequest, + }, + { + name: "duplicate changefeed returns 400", + err: cerrors.ErrChangeFeedAlreadyExists.GenWithStackByArgs("foo"), + wantStatus: http.StatusBadRequest, + }, + { + name: "unclassified error returns 500", + err: errors.New("boom"), + wantStatus: http.StatusInternalServerError, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + router := gin.New() + router.Use(ErrorHandleMiddleware()) + router.GET("/test", func(c *gin.Context) { + if tc.err != nil { + _ = c.Error(tc.err) + return + } + c.Status(http.StatusOK) + }) + + w := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodGet, "/test", nil) + router.ServeHTTP(w, req) + + require.Equal(t, tc.wantStatus, w.Code) + }) + } +} + // mockServer implements server.Server interface for testing type mockServer struct { server.Server diff --git a/pkg/api/util.go b/pkg/api/util.go index 465b8a279d..95342ce7ae 100644 --- a/pkg/api/util.go +++ b/pkg/api/util.go @@ -67,7 +67,8 @@ func NewHTTPError(err error) HTTPError { // httpBadRequestError is some errors that will cause a BadRequestError in http handler var httpBadRequestError = []*errors.Error{ cerror.ErrAPIInvalidParam, cerror.ErrSinkURIInvalid, cerror.ErrStartTsBeforeGC, - cerror.ErrChangeFeedNotExists, cerror.ErrTargetTsBeforeStartTs, cerror.ErrTableIneligible, + cerror.ErrChangeFeedNotExists, cerror.ErrChangeFeedAlreadyExists, + cerror.ErrTargetTsBeforeStartTs, cerror.ErrTableIneligible, cerror.ErrFilterRuleInvalid, cerror.ErrChangefeedUpdateRefused, cerror.ErrMySQLConnectionError, cerror.ErrMySQLInvalidConfig, cerror.ErrCaptureNotExist, cerror.ErrSchedulerRequestFailed, cerror.ErrActiveActiveTSOIndexIncompatible,