refactor: standardize response types across controllers

- Updated multiple controller methods to return VoidResponse instead of generic Response[any].
- Consolidated error handling to utilize GetErrorVoidResponse for consistent error responses.
- Enhanced parameter handling in export and file management functions for improved clarity and maintainability.
- Refactored health check and login/logout methods to align with new response structure.
- Improved overall consistency in response formatting across various endpoints.
This commit is contained in:
Marvin Zhang
2025-03-16 22:25:13 +08:00
parent 700c263cfe
commit 43d1c7692b
16 changed files with 175 additions and 135 deletions

View File

@@ -62,46 +62,46 @@ type PostBaseFileSaveOneParams struct {
Data string `json:"data"`
}
func PostBaseFileSaveOne(rootPath, path, data string) (response *Response[any], err error) {
func PostBaseFileSaveOne(rootPath, path, data string) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.Save(path, []byte(data)); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse(any(data))
return GetVoidResponse()
}
func PostBaseFileSaveOneForm(rootPath, path string, file *multipart.FileHeader) (response *Response[any], err error) {
func PostBaseFileSaveOneForm(rootPath, path string, file *multipart.FileHeader) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
f, err := file.Open()
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
fileData, err := io.ReadAll(f)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.Save(path, fileData); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func PostBaseFileSaveMany(rootPath string, form *multipart.Form) (response *Response[any], err error) {
func PostBaseFileSaveMany(rootPath string, form *multipart.Form) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
wg := sync.WaitGroup{}
@@ -140,67 +140,67 @@ func PostBaseFileSaveMany(rootPath string, form *multipart.Form) (response *Resp
}
wg.Wait()
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func PostBaseFileSaveDir(rootPath, path string) (response *Response[any], err error) {
func PostBaseFileSaveDir(rootPath, path string) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.CreateDir(path); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func PostBaseFileRename(rootPath, path, newPath string) (response *Response[any], err error) {
func PostBaseFileRename(rootPath, path, newPath string) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.Rename(path, newPath); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func DeleteBaseFile(rootPath, path string) (response *Response[any], err error) {
func DeleteBaseFile(rootPath, path string) (response *VoidResponse, err error) {
if path == "~" {
path = "."
}
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.Delete(path); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
_, err = fsSvc.GetFileInfo(".")
if err != nil {
_ = fsSvc.CreateDir("/")
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func PostBaseFileCopy(rootPath, path, newPath string) (response *Response[any], err error) {
func PostBaseFileCopy(rootPath, path, newPath string) (response *VoidResponse, err error) {
fsSvc, err := fs.GetBaseFileFsSvc(rootPath)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if err := fsSvc.Copy(path, newPath); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
func PostBaseFileExport(rootPath string, c *gin.Context) (err error) {

View File

@@ -11,18 +11,22 @@ import (
)
type PostExportParams struct {
Type string `path:"type" validate:"required"`
Target string `query:"target" validate:"required"`
Filter interfaces.Filter `query:"filter"`
Type string `path:"type" validate:"required"`
Target string `query:"target" validate:"required"`
Conditions string `query:"conditions" description:"Filter conditions. Format: [{\"key\":\"name\",\"op\":\"eq\",\"value\":\"test\"}]"`
}
func PostExport(_ *gin.Context, params *PostExportParams) (response *Response[string], err error) {
query, err := GetFilterQueryFromConditionString(params.Conditions)
if err != nil {
return GetErrorResponse[string](err)
}
var exportId string
switch params.Type {
case constants.ExportTypeCsv:
exportId, err = export.GetCsvService().Export(params.Type, params.Target, params.Filter)
exportId, err = export.GetCsvService().Export(params.Type, params.Target, query)
case constants.ExportTypeJson:
exportId, err = export.GetJsonService().Export(params.Type, params.Target, params.Filter)
exportId, err = export.GetJsonService().Export(params.Type, params.Target, query)
default:
return GetErrorResponse[string](errors.BadRequestf("invalid export type: %s", params.Type))
}

View File

@@ -10,13 +10,39 @@ import (
)
type GetFilterColFieldOptionsParams struct {
Col string `path:"col" validate:"required"`
Conditions string `query:"conditions" description:"Filter conditions. Format: [{\"key\":\"name\",\"op\":\"eq\",\"value\":\"test\"}]"`
}
func GetFilterColFieldOptions(c *gin.Context, params *GetFilterColFieldOptionsParams) (response *Response[[]entity.FilterSelectOption], err error) {
return GetFilterColFieldOptionsWithValueLabel(c, &GetFilterColFieldOptionsWithValueLabelParams{
Col: params.Col,
Conditions: params.Conditions,
})
}
type GetFilterColFieldOptionsWithValueParams struct {
Col string `path:"col" validate:"required"`
Value string `path:"value"`
Conditions string `query:"conditions" description:"Filter conditions. Format: [{\"key\":\"name\",\"op\":\"eq\",\"value\":\"test\"}]"`
}
func GetFilterColFieldOptionsWithValue(c *gin.Context, params *GetFilterColFieldOptionsWithValueParams) (response *Response[[]entity.FilterSelectOption], err error) {
return GetFilterColFieldOptionsWithValueLabel(c, &GetFilterColFieldOptionsWithValueLabelParams{
Col: params.Col,
Value: params.Value,
Conditions: params.Conditions,
})
}
type GetFilterColFieldOptionsWithValueLabelParams struct {
Col string `path:"col" validate:"required"`
Value string `path:"value"`
Label string `path:"label"`
Conditions string `query:"conditions" description:"Filter conditions. Format: [{\"key\":\"name\",\"op\":\"eq\",\"value\":\"test\"}]"`
}
func GetFilterColFieldOptions(_ *gin.Context, params *GetFilterColFieldOptionsParams) (response *Response[[]entity.FilterSelectOption], err error) {
func GetFilterColFieldOptionsWithValueLabel(_ *gin.Context, params *GetFilterColFieldOptionsWithValueLabelParams) (response *Response[[]entity.FilterSelectOption], err error) {
value := params.Value
if value == "" {
value = "_id"

View File

@@ -1,20 +1,17 @@
package controllers
import (
"errors"
"github.com/gin-gonic/gin"
"net/http"
)
func GetHealthFn(healthFn func() bool) func(c *gin.Context) error {
return func(c *gin.Context) (err error) {
func GetHealthFn(healthFn func() bool) func(c *gin.Context) {
return func(c *gin.Context) {
if healthFn() {
c.Writer.Write([]byte("ok"))
_, _ = c.Writer.Write([]byte("ok"))
c.AbortWithStatus(http.StatusOK)
return
}
c.Writer.Write([]byte("not ready"))
_, _ = c.Writer.Write([]byte("not ready"))
c.AbortWithStatus(http.StatusServiceUnavailable)
return errors.New("not ready")
}
}

View File

@@ -27,6 +27,6 @@ func PostLogin(c *gin.Context, params *PostLoginParams) (response *Response[stri
return GetDataResponse(token)
}
func PostLogout(_ *gin.Context) (response *Response[any], err error) {
return GetDataResponse[any](nil)
func PostLogout(_ *gin.Context) (response *VoidResponse, err error) {
return GetVoidResponse()
}

View File

@@ -29,7 +29,7 @@ func GetGlobalFizzWrapper() *openapi.FizzWrapper {
// NewRouterGroups initializes the router groups with their respective middleware
func NewRouterGroups(app *gin.Engine) (groups *RouterGroups) {
// Create OpenAPI wrapper
globalWrapper = openapi.NewFizzWrapper(app)
globalWrapper = openapi.GetFizzWrapper(app)
return &RouterGroups{
AuthGroup: app.Group("/", middlewares.AuthorizationMiddleware()),
@@ -485,12 +485,12 @@ func InitRoutes(app *gin.Engine) (err error) {
{
Method: http.MethodGet,
Path: "/:col/:value",
HandlerFunc: GetFilterColFieldOptions,
HandlerFunc: GetFilterColFieldOptionsWithValue,
},
{
Method: http.MethodGet,
Path: "/:col/:value/:label",
HandlerFunc: GetFilterColFieldOptions,
HandlerFunc: GetFilterColFieldOptionsWithValueLabel,
},
})
RegisterActions(groups.AuthGroup, "/settings", []Action{
@@ -543,13 +543,6 @@ func InitRoutes(app *gin.Engine) (err error) {
})
// Register public routes that don't require authentication
RegisterActions(groups.AnonymousGroup, "/health", []Action{
{
Path: "",
Method: http.MethodGet,
HandlerFunc: GetHealthFn(func() bool { return true }),
},
})
RegisterActions(groups.AnonymousGroup, "/system-info", []Action{
{
Path: "",
@@ -570,6 +563,9 @@ func InitRoutes(app *gin.Engine) (err error) {
},
})
// Register health check route
groups.AnonymousGroup.GET("/health", GetHealthFn(func() bool { return true }))
// Register OpenAPI documentation route
groups.AnonymousGroup.GET("/openapi.json", GetOpenAPI)

View File

@@ -83,26 +83,26 @@ type PostScheduleEnableDisableParams struct {
Id string `path:"id"`
}
func PostScheduleEnable(c *gin.Context, params *PostScheduleEnableDisableParams) (response *Response[any], err error) {
func PostScheduleEnable(c *gin.Context, params *PostScheduleEnableDisableParams) (response *VoidResponse, err error) {
userId := GetUserFromContext(c).Id
return postScheduleEnableDisableFunc(true, userId, params)
}
func PostScheduleDisable(c *gin.Context, params *PostScheduleEnableDisableParams) (response *Response[any], err error) {
func PostScheduleDisable(c *gin.Context, params *PostScheduleEnableDisableParams) (response *VoidResponse, err error) {
userId := GetUserFromContext(c).Id
return postScheduleEnableDisableFunc(false, userId, params)
}
func postScheduleEnableDisableFunc(isEnable bool, userId primitive.ObjectID, params *PostScheduleEnableDisableParams) (response *Response[any], err error) {
func postScheduleEnableDisableFunc(isEnable bool, userId primitive.ObjectID, params *PostScheduleEnableDisableParams) (response *VoidResponse, err error) {
id, err := primitive.ObjectIDFromHex(params.Id)
if err != nil {
return GetErrorResponse[any](errors.BadRequestf("invalid schedule id: %v", err))
return GetErrorVoidResponse(errors.BadRequestf("invalid schedule id: %v", err))
}
svc := schedule.GetScheduleService()
s, err := service.NewModelService[models.Schedule]().GetById(id)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if isEnable {
@@ -111,10 +111,10 @@ func postScheduleEnableDisableFunc(isEnable bool, userId primitive.ObjectID, par
err = svc.Disable(*s, userId)
}
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
type PostScheduleRunParams struct {

View File

@@ -575,10 +575,10 @@ type PostSpiderSaveFileParams struct {
File *multipart.FileHeader `form:"file"`
}
func PostSpiderSaveFile(c *gin.Context, params *PostSpiderSaveFileParams) (response *Response[any], err error) {
func PostSpiderSaveFile(c *gin.Context, params *PostSpiderSaveFileParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
if c.GetHeader("Content-Type") == "application/json" {
return PostBaseFileSaveOne(rootPath, params.Path, params.Data)
@@ -592,14 +592,14 @@ type PostSpiderSaveFilesParams struct {
TargetDirectory string `form:"targetDirectory"`
}
func PostSpiderSaveFiles(c *gin.Context, params *PostSpiderSaveFilesParams) (response *Response[any], err error) {
func PostSpiderSaveFiles(c *gin.Context, params *PostSpiderSaveFilesParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
form, err := c.MultipartForm()
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return PostBaseFileSaveMany(filepath.Join(rootPath, params.TargetDirectory), form)
}
@@ -609,10 +609,10 @@ type PostSpiderSaveDirParams struct {
Path string `json:"path"`
}
func PostSpiderSaveDir(c *gin.Context, params *PostSpiderSaveDirParams) (response *Response[any], err error) {
func PostSpiderSaveDir(c *gin.Context, params *PostSpiderSaveDirParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return PostBaseFileSaveDir(rootPath, params.Path)
}
@@ -623,10 +623,10 @@ type PostSpiderRenameFileParams struct {
NewPath string `json:"newPath"`
}
func PostSpiderRenameFile(c *gin.Context, params *PostSpiderRenameFileParams) (response *Response[any], err error) {
func PostSpiderRenameFile(c *gin.Context, params *PostSpiderRenameFileParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return PostBaseFileRename(rootPath, params.Path, params.NewPath)
}
@@ -636,10 +636,10 @@ type DeleteSpiderFileParams struct {
Path string `json:"path"`
}
func DeleteSpiderFile(c *gin.Context, params *DeleteSpiderFileParams) (response *Response[any], err error) {
func DeleteSpiderFile(c *gin.Context, params *DeleteSpiderFileParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return DeleteBaseFile(rootPath, params.Path)
}
@@ -650,10 +650,10 @@ type PostSpiderCopyFileParams struct {
NewPath string `json:"new_path"`
}
func PostSpiderCopyFile(c *gin.Context, params *PostSpiderCopyFileParams) (response *Response[any], err error) {
func PostSpiderCopyFile(c *gin.Context, params *PostSpiderCopyFileParams) (response *VoidResponse, err error) {
rootPath, err := getSpiderRootPathByContext(c)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return PostBaseFileCopy(rootPath, params.Path, params.NewPath)
}

View File

@@ -170,10 +170,10 @@ type DeleteTaskByIdParams struct {
Id string `path:"id"`
}
func DeleteTaskById(_ *gin.Context, params *DeleteTaskByIdParams) (response *Response[any], err error) {
func DeleteTaskById(_ *gin.Context, params *DeleteTaskByIdParams) (response *VoidResponse, err error) {
id, err := primitive.ObjectIDFromHex(params.Id)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
// delete in db
@@ -202,7 +202,7 @@ func DeleteTaskById(_ *gin.Context, params *DeleteTaskByIdParams) (response *Res
return nil
}); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
// delete task logs
@@ -211,19 +211,19 @@ func DeleteTaskById(_ *gin.Context, params *DeleteTaskByIdParams) (response *Res
logger.Warnf("failed to remove task log directory: %s", logPath)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
type DeleteTaskListParams struct {
Ids []string `json:"ids"`
}
func DeleteList(_ *gin.Context, params *DeleteTaskListParams) (response *Response[any], err error) {
func DeleteList(_ *gin.Context, params *DeleteTaskListParams) (response *VoidResponse, err error) {
var ids []primitive.ObjectID
for _, id := range params.Ids {
id, err := primitive.ObjectIDFromHex(id)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
ids = append(ids, id)
}
@@ -250,7 +250,7 @@ func DeleteList(_ *gin.Context, params *DeleteTaskListParams) (response *Respons
return nil
}); err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
// delete tasks logs
@@ -268,7 +268,7 @@ func DeleteList(_ *gin.Context, params *DeleteTaskListParams) (response *Respons
}
wg.Wait()
return GetDataResponse[any](nil)
return GetVoidResponse()
}
type PostTaskRunParams struct {
@@ -379,22 +379,22 @@ type PostTaskCancelParams struct {
Force bool `json:"force,omitempty"`
}
func PostTaskCancel(c *gin.Context, params *PostTaskCancelParams) (response *Response[any], err error) {
func PostTaskCancel(c *gin.Context, params *PostTaskCancelParams) (response *VoidResponse, err error) {
// id
id, err := primitive.ObjectIDFromHex(params.Id)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
// task
t, err := service.NewModelService[models.Task]().GetById(id)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
// validate
if !utils.IsCancellable(t.Status) {
return GetErrorResponse[any](errors.New("task is not cancellable"))
return GetErrorVoidResponse(errors.New("task is not cancellable"))
}
u := GetUserFromContext(c)
@@ -403,10 +403,10 @@ func PostTaskCancel(c *gin.Context, params *PostTaskCancelParams) (response *Res
schedulerSvc := scheduler.GetTaskSchedulerService()
err = schedulerSvc.Cancel(id, u.Id, params.Force)
if err != nil {
return GetErrorResponse[any](err)
return GetErrorVoidResponse(err)
}
return GetDataResponse[any](nil)
return GetVoidResponse()
}
type GetTaskLogsParams struct {

View File

@@ -263,6 +263,12 @@ type ListResponse[T any] struct {
Error string `json:"error"`
}
type VoidResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Error string `json:"error"`
}
func GetDataResponse[T any](model T) (res *Response[T], err error) {
return &Response[T]{
Status: constants.HttpResponseStatusOk,
@@ -280,6 +286,13 @@ func GetListResponse[T any](models []T, total int) (res *ListResponse[T], err er
}, nil
}
func GetVoidResponse() (res *VoidResponse, err error) {
return &VoidResponse{
Status: constants.HttpResponseStatusOk,
Message: constants.HttpResponseMessageSuccess,
}, nil
}
func GetErrorResponse[T any](err error) (res *Response[T], err2 error) {
return &Response[T]{
Status: constants.HttpResponseStatusOk,
@@ -288,6 +301,14 @@ func GetErrorResponse[T any](err error) (res *Response[T], err2 error) {
}, err
}
func GetErrorVoidResponse(err error) (res *VoidResponse, err2 error) {
return &VoidResponse{
Status: constants.HttpResponseStatusOk,
Message: constants.HttpResponseMessageError,
Error: err.Error(),
}, err
}
func GetErrorListResponse[T any](err error) (res *ListResponse[T], err2 error) {
return &ListResponse[T]{
Status: constants.HttpResponseStatusOk,