mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
feat: enhance API routing and OpenAPI documentation support
- Introduced a new OpenAPI wrapper using Fizz for improved API documentation - Refactored base controller to support more flexible route handling - Added dynamic route registration with OpenAPI metadata - Implemented generic response types for consistent API responses - Updated router initialization to support OpenAPI documentation endpoint - Improved route and resource naming utilities - Migrated existing controllers to use new routing and response mechanisms
This commit is contained in:
@@ -50,7 +50,7 @@ func (app *Api) Start() {
|
||||
|
||||
// http server
|
||||
app.srv = &http.Server{
|
||||
Handler: app.app,
|
||||
Handler: app.GetHttpServerHandler(),
|
||||
Addr: address,
|
||||
}
|
||||
|
||||
@@ -85,6 +85,10 @@ func (app *Api) Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (app *Api) GetHttpServerHandler() http.Handler {
|
||||
return controllers.GetGlobalFizzWrapper().GetFizz()
|
||||
}
|
||||
|
||||
func (app *Api) GetGinEngine() *gin.Engine {
|
||||
return app.app
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ package apps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"sync"
|
||||
|
||||
"github.com/crawlab-team/crawlab/core/interfaces"
|
||||
"github.com/crawlab-team/crawlab/core/node/service"
|
||||
"github.com/crawlab-team/crawlab/core/utils"
|
||||
"github.com/spf13/viper"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/crawlab-team/crawlab/core/entity"
|
||||
"github.com/crawlab-team/crawlab/core/interfaces"
|
||||
"github.com/crawlab-team/crawlab/core/models/service"
|
||||
"github.com/crawlab-team/crawlab/core/mongo"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/juju/errors"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
mongo2 "go.mongodb.org/mongo-driver/mongo"
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
type Action struct {
|
||||
Method string
|
||||
Path string
|
||||
HandlerFunc gin.HandlerFunc
|
||||
HandlerFunc interface{}
|
||||
}
|
||||
|
||||
type BaseController[T any] struct {
|
||||
@@ -22,39 +23,68 @@ type BaseController[T any] struct {
|
||||
actions []Action
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) GetById(c *gin.Context) {
|
||||
id, err := primitive.ObjectIDFromHex(c.Param("id"))
|
||||
type GetByIdParams struct {
|
||||
Id string `path:"id" description:"The ID of the item to get"`
|
||||
}
|
||||
|
||||
// GetAllParams represents parameters for GetAll method
|
||||
type GetAllParams struct {
|
||||
Query bson.M `json:"query"`
|
||||
Sort bson.D `json:"sort"`
|
||||
}
|
||||
|
||||
// GetListParams represents parameters for GetList with pagination
|
||||
type GetListParams struct {
|
||||
Query bson.M `json:"query"`
|
||||
Sort bson.D `json:"sort"`
|
||||
Pagination *entity.Pagination `json:"pagination"`
|
||||
All bool `query:"all" description:"Whether to get all items"`
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) GetById(_ *gin.Context, params *GetByIdParams) (response *Response[T], err error) {
|
||||
id, err := primitive.ObjectIDFromHex(params.Id)
|
||||
if err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return nil, errors.BadRequestf("invalid id: %s", params.Id)
|
||||
}
|
||||
|
||||
model, err := ctr.modelSvc.GetById(id)
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
HandleSuccessWithData(c, model)
|
||||
return GetSuccessDataResponse(*model)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) GetList(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) GetList(c *gin.Context, params *GetListParams) (response *ListResponse[T], err error) {
|
||||
// get all if query field "all" is set true
|
||||
all := MustGetFilterAll(c)
|
||||
all := params.All || MustGetFilterAll(c)
|
||||
|
||||
// Prepare parameters
|
||||
query := MustGetFilterQuery(c)
|
||||
sort := MustGetSortOption(c)
|
||||
|
||||
if all {
|
||||
ctr.getAll(c)
|
||||
return
|
||||
allParams := &GetAllParams{
|
||||
Query: query,
|
||||
Sort: sort,
|
||||
}
|
||||
return ctr.GetAll(c, allParams)
|
||||
}
|
||||
|
||||
// get list
|
||||
ctr.getList(c)
|
||||
// get list with pagination
|
||||
pagination := MustGetPagination(c)
|
||||
listParams := &GetListParams{
|
||||
Query: query,
|
||||
Sort: sort,
|
||||
Pagination: pagination,
|
||||
}
|
||||
return ctr.GetWithPagination(c, listParams)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) Post(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) Post(c *gin.Context) (response *Response[T], err error) {
|
||||
var model T
|
||||
if err := c.ShouldBindJSON(&model); err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
u := GetUserFromContext(c)
|
||||
m := any(&model).(interfaces.Model)
|
||||
@@ -64,30 +94,26 @@ func (ctr *BaseController[T]) Post(c *gin.Context) {
|
||||
col := ctr.modelSvc.GetCol()
|
||||
res, err := col.GetCollection().InsertOne(col.GetContext(), m)
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
result, err := ctr.modelSvc.GetById(res.InsertedID.(primitive.ObjectID))
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
HandleSuccessWithData(c, result)
|
||||
return GetSuccessDataResponse(*result)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) PutById(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) PutById(c *gin.Context) (response *Response[T], err error) {
|
||||
id, err := primitive.ObjectIDFromHex(c.Param("id"))
|
||||
if err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
var model T
|
||||
if err := c.ShouldBindJSON(&model); err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
u := GetUserFromContext(c)
|
||||
@@ -95,20 +121,18 @@ func (ctr *BaseController[T]) PutById(c *gin.Context) {
|
||||
m.SetUpdated(u.Id)
|
||||
|
||||
if err := ctr.modelSvc.ReplaceById(id, model); err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
result, err := ctr.modelSvc.GetById(id)
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
HandleSuccessWithData(c, result)
|
||||
return GetSuccessDataResponse(*result)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) PatchList(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) PatchList(c *gin.Context) (res *Response[T], err error) {
|
||||
type Payload struct {
|
||||
Ids []primitive.ObjectID `json:"ids"`
|
||||
Update bson.M `json:"update"`
|
||||
@@ -116,8 +140,7 @@ func (ctr *BaseController[T]) PatchList(c *gin.Context) {
|
||||
|
||||
var payload Payload
|
||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
// query
|
||||
@@ -129,45 +152,43 @@ func (ctr *BaseController[T]) PatchList(c *gin.Context) {
|
||||
|
||||
// update
|
||||
if err := ctr.modelSvc.UpdateMany(query, bson.M{"$set": payload.Update}); err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
HandleSuccess(c)
|
||||
// Return an empty response with success status
|
||||
var emptyModel T
|
||||
return GetSuccessDataResponse(emptyModel)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) DeleteById(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) DeleteById(c *gin.Context) (res *Response[T], err error) {
|
||||
id, err := primitive.ObjectIDFromHex(c.Param("id"))
|
||||
if err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
if err := ctr.modelSvc.DeleteById(id); err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
HandleSuccess(c)
|
||||
var emptyModel T
|
||||
return GetSuccessDataResponse(emptyModel)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) DeleteList(c *gin.Context) {
|
||||
func (ctr *BaseController[T]) DeleteList(c *gin.Context) (res *Response[T], err error) {
|
||||
type Payload struct {
|
||||
Ids []string `json:"ids"`
|
||||
}
|
||||
|
||||
var payload Payload
|
||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
var ids []primitive.ObjectID
|
||||
for _, id := range payload.Ids {
|
||||
objectId, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
HandleErrorBadRequest(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
ids = append(ids, objectId)
|
||||
}
|
||||
@@ -177,39 +198,46 @@ func (ctr *BaseController[T]) DeleteList(c *gin.Context) {
|
||||
"$in": ids,
|
||||
},
|
||||
}); err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return GetErrorDataResponse[T](err)
|
||||
}
|
||||
|
||||
HandleSuccess(c)
|
||||
var emptyModel T
|
||||
return GetSuccessDataResponse(emptyModel)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) getAll(c *gin.Context) {
|
||||
query := MustGetFilterQuery(c)
|
||||
sort := MustGetSortOption(c)
|
||||
// GetAll retrieves all items based on filter and sort
|
||||
func (ctr *BaseController[T]) GetAll(_ *gin.Context, params *GetAllParams) (response *ListResponse[T], err error) {
|
||||
query := params.Query
|
||||
sort := params.Sort
|
||||
if sort == nil {
|
||||
sort = bson.D{{"_id", -1}}
|
||||
}
|
||||
|
||||
models, err := ctr.modelSvc.GetMany(query, &mongo.FindOptions{
|
||||
Sort: sort,
|
||||
})
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
total, err := ctr.modelSvc.Count(query)
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
HandleSuccessWithListData(c, models, total)
|
||||
|
||||
return GetSuccessListResponse(models, total)
|
||||
}
|
||||
|
||||
func (ctr *BaseController[T]) getList(c *gin.Context) {
|
||||
// GetWithPagination retrieves items with pagination
|
||||
func (ctr *BaseController[T]) GetWithPagination(_ *gin.Context, params *GetListParams) (response *ListResponse[T], err error) {
|
||||
// params
|
||||
pagination := MustGetPagination(c)
|
||||
query := MustGetFilterQuery(c)
|
||||
sort := MustGetSortOption(c)
|
||||
pagination := params.Pagination
|
||||
query := params.Query
|
||||
sort := params.Sort
|
||||
|
||||
if pagination == nil {
|
||||
pagination = GetDefaultPagination()
|
||||
}
|
||||
|
||||
// get list
|
||||
models, err := ctr.modelSvc.GetMany(query, &mongo.FindOptions{
|
||||
@@ -219,22 +247,49 @@ func (ctr *BaseController[T]) getList(c *gin.Context) {
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo2.ErrNoDocuments) {
|
||||
HandleSuccessWithListData(c, nil, 0)
|
||||
return GetSuccessListResponse[T](nil, 0)
|
||||
} else {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// total count
|
||||
total, err := ctr.modelSvc.Count(query)
|
||||
if err != nil {
|
||||
HandleErrorInternalServerError(c, err)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// response
|
||||
HandleSuccessWithListData(c, models, total)
|
||||
return GetSuccessListResponse(models, total)
|
||||
}
|
||||
|
||||
// getAll is kept for backward compatibility
|
||||
func (ctr *BaseController[T]) getAll(c *gin.Context) (response *ListResponse[T], err error) {
|
||||
query := MustGetFilterQuery(c)
|
||||
sort := MustGetSortOption(c)
|
||||
|
||||
params := &GetAllParams{
|
||||
Query: query,
|
||||
Sort: sort,
|
||||
}
|
||||
|
||||
return ctr.GetAll(c, params)
|
||||
}
|
||||
|
||||
// getList is kept for backward compatibility
|
||||
func (ctr *BaseController[T]) getList(c *gin.Context) (response *ListResponse[T], err error) {
|
||||
// params
|
||||
pagination := MustGetPagination(c)
|
||||
query := MustGetFilterQuery(c)
|
||||
sort := MustGetSortOption(c)
|
||||
|
||||
params := &GetListParams{
|
||||
Query: query,
|
||||
Sort: sort,
|
||||
Pagination: pagination,
|
||||
}
|
||||
|
||||
return ctr.GetWithPagination(c, params)
|
||||
}
|
||||
|
||||
func NewController[T any](actions ...Action) *BaseController[T] {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package controllers
|
||||
|
||||
type Response[T any] struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type ListResponse[T any] struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Data []T `json:"data"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
16
core/controllers/openapi.go
Normal file
16
core/controllers/openapi.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/wI2L/fizz/openapi"
|
||||
)
|
||||
|
||||
func GetOpenAPI(c *gin.Context) {
|
||||
info := &openapi.Info{
|
||||
Title: "Crawlab API",
|
||||
Description: "REST API for Crawlab",
|
||||
Version: "0.7.0",
|
||||
}
|
||||
handleFunc := globalWrapper.GetFizz().OpenAPI(info, "json")
|
||||
handleFunc(c)
|
||||
}
|
||||
@@ -2,25 +2,40 @@ package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/crawlab-team/crawlab/core/middlewares"
|
||||
"github.com/crawlab-team/crawlab/core/models/models"
|
||||
"github.com/crawlab-team/crawlab/core/openapi"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// RouterGroups defines the different authentication levels for API routes
|
||||
type RouterGroups struct {
|
||||
AuthGroup *gin.RouterGroup // Routes requiring full authentication
|
||||
SyncAuthGroup *gin.RouterGroup // Routes for sync operations with special auth
|
||||
AnonymousGroup *gin.RouterGroup // Public routes that don't require auth
|
||||
AuthGroup *gin.RouterGroup // Routes requiring full authentication
|
||||
SyncAuthGroup *gin.RouterGroup // Routes for sync operations with special auth
|
||||
AnonymousGroup *gin.RouterGroup // Public routes that don't require auth
|
||||
Wrapper *openapi.FizzWrapper // OpenAPI wrapper for documentation
|
||||
}
|
||||
|
||||
// Global variable to store the OpenAPI wrapper
|
||||
// This is a workaround since we can't easily pass it through the Gin context
|
||||
var globalWrapper *openapi.FizzWrapper
|
||||
|
||||
func GetGlobalFizzWrapper() *openapi.FizzWrapper {
|
||||
return globalWrapper
|
||||
}
|
||||
|
||||
// NewRouterGroups initializes the router groups with their respective middleware
|
||||
func NewRouterGroups(app *gin.Engine) (groups *RouterGroups) {
|
||||
// Create OpenAPI wrapper
|
||||
wrapper := openapi.NewFizzWrapper(app)
|
||||
|
||||
return &RouterGroups{
|
||||
AuthGroup: app.Group("/", middlewares.AuthorizationMiddleware()),
|
||||
SyncAuthGroup: app.Group("/", middlewares.SyncAuthorizationMiddleware()),
|
||||
AnonymousGroup: app.Group("/"),
|
||||
Wrapper: wrapper,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,36 +45,170 @@ func RegisterController[T any](group *gin.RouterGroup, basePath string, ctr *Bas
|
||||
// Track registered paths to avoid duplicates
|
||||
actionPaths := make(map[string]bool)
|
||||
for _, action := range ctr.actions {
|
||||
group.Handle(action.Method, basePath+action.Path, action.HandlerFunc)
|
||||
path := basePath + action.Path
|
||||
key := action.Method + " - " + path
|
||||
actionPaths[key] = true
|
||||
|
||||
// Create appropriate model response based on the action
|
||||
responses := globalWrapper.BuildModelResponse()
|
||||
|
||||
id := getIDForAction(action.Method, path)
|
||||
summary := getSummaryForAction(action.Method, basePath, action.Path)
|
||||
description := getDescriptionForAction(action.Method, basePath, action.Path)
|
||||
|
||||
globalWrapper.RegisterRoute(action.Method, path, action.HandlerFunc, id, summary, description, responses)
|
||||
}
|
||||
registerBuiltinHandler(group, http.MethodGet, basePath+"", ctr.GetList, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodGet, basePath+"/:id", ctr.GetById, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodPost, basePath+"", ctr.Post, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodPut, basePath+"/:id", ctr.PutById, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodPatch, basePath+"", ctr.PatchList, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodDelete, basePath+"/:id", ctr.DeleteById, actionPaths)
|
||||
registerBuiltinHandler(group, http.MethodDelete, basePath+"", ctr.DeleteList, actionPaths)
|
||||
|
||||
// Register built-in handlers if they haven't been overridden
|
||||
// Create a zero value of T to use as the model
|
||||
var model T
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodGet, "", ctr.GetList, actionPaths, "Get list", "Get a list of items", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodGet, "/:id", ctr.GetById, actionPaths, "Get by ID", "Get a single item by ID", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodPost, "", ctr.Post, actionPaths, "Create", "Create a new item", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodPut, "/:id", ctr.PutById, actionPaths, "Update by ID", "Update an item by ID", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodPatch, "", ctr.PatchList, actionPaths, "Patch list", "Patch multiple items", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodDelete, "/:id", ctr.DeleteById, actionPaths, "Delete by ID", "Delete an item by ID", model)
|
||||
registerBuiltinHandler(group, globalWrapper, basePath, http.MethodDelete, "", ctr.DeleteList, actionPaths, "Delete list", "Delete multiple items", model)
|
||||
}
|
||||
|
||||
// RegisterActions registers a list of custom action handlers to a route group
|
||||
func RegisterActions(group *gin.RouterGroup, basePath string, actions []Action) {
|
||||
for _, action := range actions {
|
||||
group.Handle(action.Method, basePath+action.Path, action.HandlerFunc)
|
||||
path := basePath + action.Path
|
||||
|
||||
// Create generic response
|
||||
responses := globalWrapper.BuildModelResponse()
|
||||
|
||||
id := getIDForAction(action.Method, path)
|
||||
summary := getSummaryForAction(action.Method, basePath, action.Path)
|
||||
description := getDescriptionForAction(action.Method, basePath, action.Path)
|
||||
|
||||
globalWrapper.RegisterRoute(action.Method, path, action.HandlerFunc, id, summary, description, responses)
|
||||
}
|
||||
}
|
||||
|
||||
// registerBuiltinHandler registers a standard handler if it hasn't been overridden
|
||||
// by a custom action
|
||||
func registerBuiltinHandler(group *gin.RouterGroup, method, path string, handlerFunc gin.HandlerFunc, existingActionPaths map[string]bool) {
|
||||
func registerBuiltinHandler[T any](group *gin.RouterGroup, wrapper *openapi.FizzWrapper, basePath, method, pathSuffix string, handlerFunc interface{}, existingActionPaths map[string]bool, summary, description string, model T) {
|
||||
path := basePath + pathSuffix
|
||||
key := method + " - " + path
|
||||
_, ok := existingActionPaths[key]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
group.Handle(method, path, handlerFunc)
|
||||
|
||||
id := getIDForAction(method, path)
|
||||
|
||||
// Create appropriate response based on the method
|
||||
responses := wrapper.BuildModelResponse()
|
||||
|
||||
wrapper.RegisterRoute(method, path, handlerFunc, id, summary, description, responses)
|
||||
}
|
||||
|
||||
// Helper functions to generate OpenAPI documentation
|
||||
func getIDForAction(method, path string) string {
|
||||
// Remove leading slash and convert remaining slashes to underscores
|
||||
cleanPath := strings.TrimPrefix(path, "/")
|
||||
cleanPath = strings.ReplaceAll(cleanPath, "/", "_")
|
||||
cleanPath = strings.ReplaceAll(cleanPath, ":", "_")
|
||||
cleanPath = strings.ReplaceAll(cleanPath, "__", "_")
|
||||
|
||||
return method + "_" + cleanPath
|
||||
}
|
||||
|
||||
func getSummaryForAction(method, basePath, path string) string {
|
||||
resource := getResourceName(basePath)
|
||||
|
||||
switch method {
|
||||
case http.MethodGet:
|
||||
if path == "" {
|
||||
return "List " + resource
|
||||
} else if path == "/:id" {
|
||||
return "Get " + resource + " by ID"
|
||||
}
|
||||
case http.MethodPost:
|
||||
if path == "" {
|
||||
return "Create " + resource
|
||||
}
|
||||
case http.MethodPut:
|
||||
if path == "/:id" {
|
||||
return "Update " + resource + " by ID"
|
||||
}
|
||||
case http.MethodPatch:
|
||||
if path == "" {
|
||||
return "Patch " + resource + " list"
|
||||
}
|
||||
case http.MethodDelete:
|
||||
if path == "/:id" {
|
||||
return "Delete " + resource + " by ID"
|
||||
} else if path == "" {
|
||||
return "Delete " + resource + " list"
|
||||
}
|
||||
}
|
||||
|
||||
// For custom actions, use a more descriptive summary
|
||||
if path != "" && path != "/:id" {
|
||||
return method + " " + resource + path
|
||||
}
|
||||
|
||||
return method + " " + resource
|
||||
}
|
||||
|
||||
func getDescriptionForAction(method, basePath, path string) string {
|
||||
resource := getResourceName(basePath)
|
||||
|
||||
switch method {
|
||||
case http.MethodGet:
|
||||
if path == "" {
|
||||
return "Get a list of " + resource + " items"
|
||||
} else if path == "/:id" {
|
||||
return "Get a single " + resource + " by ID"
|
||||
}
|
||||
case http.MethodPost:
|
||||
if path == "" {
|
||||
return "Create a new " + resource
|
||||
}
|
||||
case http.MethodPut:
|
||||
if path == "/:id" {
|
||||
return "Update a " + resource + " by ID"
|
||||
}
|
||||
case http.MethodPatch:
|
||||
if path == "" {
|
||||
return "Patch multiple " + resource + " items"
|
||||
}
|
||||
case http.MethodDelete:
|
||||
if path == "/:id" {
|
||||
return "Delete a " + resource + " by ID"
|
||||
} else if path == "" {
|
||||
return "Delete multiple " + resource + " items"
|
||||
}
|
||||
}
|
||||
|
||||
// For custom actions, use a more descriptive description
|
||||
if path != "" && path != "/:id" {
|
||||
return "Perform " + method + " operation on " + resource + " with path " + path
|
||||
}
|
||||
|
||||
return "Perform " + method + " operation on " + resource
|
||||
}
|
||||
|
||||
func getResourceName(basePath string) string {
|
||||
// Remove leading slash and get the last part of the path
|
||||
if len(basePath) > 0 && basePath[0] == '/' {
|
||||
basePath = basePath[1:]
|
||||
}
|
||||
|
||||
// Remove trailing slash if present
|
||||
if len(basePath) > 0 && basePath[len(basePath)-1] == '/' {
|
||||
basePath = basePath[:len(basePath)-1]
|
||||
}
|
||||
|
||||
// If path is empty, return "resource"
|
||||
if basePath == "" {
|
||||
return "resource"
|
||||
}
|
||||
|
||||
return basePath
|
||||
}
|
||||
|
||||
// InitRoutes configures all API routes for the application
|
||||
@@ -67,6 +216,9 @@ func InitRoutes(app *gin.Engine) (err error) {
|
||||
// Initialize route groups with different auth levels
|
||||
groups := NewRouterGroups(app)
|
||||
|
||||
// Store the wrapper in the global variable for later use
|
||||
globalWrapper = groups.Wrapper
|
||||
|
||||
// Register resource controllers with their respective endpoints
|
||||
// Each RegisterController call sets up standard CRUD operations
|
||||
// Additional custom actions can be specified in the controller initialization
|
||||
@@ -418,5 +570,8 @@ func InitRoutes(app *gin.Engine) (err error) {
|
||||
},
|
||||
})
|
||||
|
||||
// Register OpenAPI documentation route
|
||||
groups.AnonymousGroup.GET("/openapi.json", GetOpenAPI)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func GetSpiderById(c *gin.Context) {
|
||||
HandleSuccessWithData(c, s)
|
||||
}
|
||||
|
||||
func GetSpiderList(c *gin.Context) {
|
||||
func GetSpiderList(c *gin.Context, params *GetListParams) {
|
||||
// get all list
|
||||
all := MustGetFilterAll(c)
|
||||
if all {
|
||||
@@ -85,7 +85,7 @@ func GetSpiderList(c *gin.Context) {
|
||||
// get list
|
||||
withStats := c.Query("stats")
|
||||
if withStats == "" {
|
||||
NewController[models.Spider]().GetList(c)
|
||||
NewController[models.Spider]().GetList(c, params)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -67,10 +67,10 @@ func GetTaskById(c *gin.Context) {
|
||||
HandleSuccessWithData(c, t)
|
||||
}
|
||||
|
||||
func GetTaskList(c *gin.Context) {
|
||||
func GetTaskList(c *gin.Context, params *GetListParams) {
|
||||
withStats := c.Query("stats")
|
||||
if withStats == "" {
|
||||
NewController[models.Task]().GetList(c)
|
||||
NewController[models.Task]().GetList(c, params)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,55 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/crawlab-team/crawlab/core/constants"
|
||||
"github.com/crawlab-team/crawlab/core/entity"
|
||||
"github.com/crawlab-team/crawlab/core/utils"
|
||||
"github.com/crawlab-team/crawlab/trace"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Response[T any] struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type ListResponse[T any] struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Data []T `json:"data"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func GetSuccessDataResponse[T any](model T) (res *Response[T], err error) {
|
||||
return &Response[T]{
|
||||
Status: constants.HttpResponseStatusOk,
|
||||
Message: constants.HttpResponseMessageSuccess,
|
||||
Data: model,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetSuccessListResponse[T any](models []T, total int) (res *ListResponse[T], err error) {
|
||||
return &ListResponse[T]{
|
||||
Status: constants.HttpResponseStatusOk,
|
||||
Message: constants.HttpResponseMessageSuccess,
|
||||
Data: models,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetErrorDataResponse[T any](err error) (res *Response[T], err2 error) {
|
||||
return &Response[T]{
|
||||
Status: constants.HttpResponseStatusOk,
|
||||
Message: constants.HttpResponseMessageError,
|
||||
Error: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
func handleError(statusCode int, c *gin.Context, err error) {
|
||||
if utils.IsDev() {
|
||||
trace.PrintError(err)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/crawlab-team/crawlab/core
|
||||
|
||||
go 1.22.9
|
||||
go 1.23
|
||||
|
||||
replace (
|
||||
github.com/crawlab-team/crawlab/grpc => ../grpc
|
||||
@@ -26,6 +26,7 @@ require (
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-uuid v1.0.3
|
||||
github.com/juju/errors v1.0.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/robfig/cron/v3 v3.0.0
|
||||
@@ -33,8 +34,10 @@ require (
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/wI2L/fizz v0.22.0
|
||||
go.mongodb.org/mongo-driver v1.15.1
|
||||
golang.org/x/oauth2 v0.23.0
|
||||
golang.org/x/text v0.21.0
|
||||
google.golang.org/api v0.189.0
|
||||
google.golang.org/grpc v1.69.2
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
@@ -72,6 +75,7 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
@@ -86,6 +90,7 @@ require (
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/loopfz/gadgeto v0.9.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
@@ -128,10 +133,10 @@ require (
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/go-playground/validator.v9 v9.30.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
56
core/go.sum
56
core/go.sum
@@ -61,6 +61,8 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Pallinder/go-randomdata v1.2.0 h1:DZ41wBchNRb/0GfsePLiSwb0PHZmT67XY00lCDlaYPg=
|
||||
github.com/Pallinder/go-randomdata v1.2.0/go.mod h1:yHmJgulpD2Nfrm0cR9tI/+oAgRqCQQixsA8HyRZfV9Y=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
|
||||
@@ -134,6 +136,7 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -169,8 +172,14 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/cors v1.3.0/go.mod h1:artPvLlhkF7oG06nK8v3U8TNz6IeX+w1uzCSEId5/Vc=
|
||||
github.com/gin-contrib/sse v0.0.0-20190125020943-a7658810eb74/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
|
||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
@@ -197,18 +206,29 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
@@ -290,6 +310,7 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -361,6 +382,9 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
@@ -377,14 +401,21 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/loopfz/gadgeto v0.9.0 h1:yrQVBgdGhAWOB+JjH98sJzYfSqpcpKzOBIEtJFcRl2s=
|
||||
github.com/loopfz/gadgeto v0.9.0/go.mod h1:S3tK5SXmKY3l39rUpPZw1B/iiy1CftV13QABFhj32Ss=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
@@ -397,7 +428,9 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
@@ -440,6 +473,7 @@ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -467,6 +501,8 @@ github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
|
||||
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -542,8 +578,17 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||
github.com/ugorji/go/codec v0.0.0-20190128213124-ee1426cffec0/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/wI2L/fizz v0.22.0 h1:mgRA+uUdESvgsIeBFkMSS/MEIQ4EZ4I2xyRxnCqkhJY=
|
||||
github.com/wI2L/fizz v0.22.0/go.mod h1:CMxMR1amz8id9wr2YUpONf+F/F9hW1cqRXxVNNuWVxE=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
@@ -612,8 +657,10 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
@@ -811,6 +858,7 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1074,11 +1122,18 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/go-playground/validator.v9 v9.26.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss=
|
||||
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
@@ -1088,6 +1143,7 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/apex/log"
|
||||
"github.com/crawlab-team/crawlab/core/entity"
|
||||
"github.com/crawlab-team/crawlab/core/utils"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -23,7 +22,7 @@ type ResBody struct {
|
||||
}
|
||||
|
||||
// RequestParam represents parameters for HTTP requests
|
||||
type RequestParam entity.RequestParam
|
||||
type RequestParam map[string]interface{}
|
||||
|
||||
// performRequest performs an HTTP request with JSON body
|
||||
func performRequest(method, url string, data interface{}) (*http.Response, []byte, error) {
|
||||
|
||||
116
core/openapi/wrapper.go
Normal file
116
core/openapi/wrapper.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package openapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/loopfz/gadgeto/tonic"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/wI2L/fizz"
|
||||
)
|
||||
|
||||
// FizzWrapper wraps an existing Gin Engine to add OpenAPI functionality
|
||||
type FizzWrapper struct {
|
||||
fizz *fizz.Fizz
|
||||
gin *gin.Engine
|
||||
}
|
||||
|
||||
// NewFizzWrapper creates a new wrapper around an existing Gin Engine
|
||||
// This approach ensures we don't break existing functionality
|
||||
func NewFizzWrapper(engine *gin.Engine) *FizzWrapper {
|
||||
// Create a new Fizz instance using the existing Gin engine
|
||||
f := fizz.NewFromEngine(engine)
|
||||
|
||||
return &FizzWrapper{
|
||||
fizz: f,
|
||||
gin: engine,
|
||||
}
|
||||
}
|
||||
|
||||
// GetFizz returns the underlying Fizz instance
|
||||
func (w *FizzWrapper) GetFizz() *fizz.Fizz {
|
||||
return w.fizz
|
||||
}
|
||||
|
||||
// GetGin returns the underlying Gin engine
|
||||
func (w *FizzWrapper) GetGin() *gin.Engine {
|
||||
return w.gin
|
||||
}
|
||||
|
||||
// Response represents an OpenAPI response
|
||||
type Response struct {
|
||||
Description string
|
||||
Model interface{}
|
||||
}
|
||||
|
||||
// RegisterRoute registers a route with OpenAPI documentation
|
||||
func (w *FizzWrapper) RegisterRoute(method, path string, handler interface{}, id, summary, description string, responses map[int]Response) {
|
||||
// Build operation options for OpenAPI documentation
|
||||
opts := w.buildOperationOptions(id, summary, description, responses)
|
||||
|
||||
// Register the route with OpenAPI documentation
|
||||
switch method {
|
||||
case "GET":
|
||||
w.fizz.GET(path, opts, tonic.Handler(handler, 200))
|
||||
case "POST":
|
||||
w.fizz.POST(path, opts, tonic.Handler(handler, 200))
|
||||
case "PUT":
|
||||
w.fizz.PUT(path, opts, tonic.Handler(handler, 200))
|
||||
case "DELETE":
|
||||
w.fizz.DELETE(path, opts, tonic.Handler(handler, 200))
|
||||
case "PATCH":
|
||||
w.fizz.PATCH(path, opts, tonic.Handler(handler, 200))
|
||||
case "HEAD":
|
||||
w.fizz.HEAD(path, opts, tonic.Handler(handler, 200))
|
||||
case "OPTIONS":
|
||||
w.fizz.OPTIONS(path, opts, tonic.Handler(handler, 200))
|
||||
}
|
||||
}
|
||||
|
||||
// BuildModelResponse builds a standard response model with a specific data type
|
||||
func (w *FizzWrapper) BuildModelResponse() map[int]Response {
|
||||
return map[int]Response{
|
||||
400: {
|
||||
Description: "Bad Request",
|
||||
},
|
||||
401: {
|
||||
Description: "Unauthorized",
|
||||
},
|
||||
500: {
|
||||
Description: "Internal Server Error",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// buildOperationOptions builds the options for a Fizz operation
|
||||
func (w *FizzWrapper) buildOperationOptions(id, summary, description string, responses map[int]Response) []fizz.OperationOption {
|
||||
var opts []fizz.OperationOption
|
||||
|
||||
// Add ID
|
||||
if id != "" {
|
||||
opts = append(opts, fizz.ID(id))
|
||||
}
|
||||
|
||||
// Add summary
|
||||
if summary != "" {
|
||||
opts = append(opts, fizz.Summary(summary))
|
||||
}
|
||||
|
||||
// Add description
|
||||
if description != "" {
|
||||
opts = append(opts, fizz.Description(description))
|
||||
}
|
||||
|
||||
// Add responses
|
||||
if responses != nil {
|
||||
for status, response := range responses {
|
||||
if response.Model != nil {
|
||||
opts = append(opts, fizz.Response(fmt.Sprintf("%d", status), response.Description, response.Model, nil, nil))
|
||||
} else {
|
||||
opts = append(opts, fizz.Response(fmt.Sprintf("%d", status), response.Description, nil, nil, nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
13
go.work.sum
13
go.work.sum
@@ -821,7 +821,6 @@ github.com/crawlab-team/crawlab/template-parser v0.0.0-20240614095218-7b4ee8399a
|
||||
github.com/crawlab-team/crawlab/template-parser v0.0.0-20241016121324-eb56598d93dc/go.mod h1:lKaowLGJrCwvFJnW/KYbdz0Pj69My34yus6IsLKDMro=
|
||||
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -844,6 +843,7 @@ github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CA
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/gin-contrib/cors v1.3.0 h1:PolezCc89peu+NgkIWt9OB01Kbzt6IP0J/JvkG6xxlg=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df h1:Bao6dhmbTA1KFVxmJ6nBoMuOJit2yjEgLJpIMYpop0E=
|
||||
@@ -972,6 +972,11 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
|
||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 h1:K//n/AqR5HjG3qxbrBCL4vJPW0MVFSs9CPK1OOJdRME=
|
||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
||||
github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9 h1:hJix6idebFclqlfZCHE7EUX7uqLCyb70nHNHH1XKGBg=
|
||||
github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
|
||||
github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
|
||||
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 h1:Pp8RxiF4rSoXP9SED26WCfNB28/dwTDpPXS8XMJR8rc=
|
||||
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
|
||||
github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
@@ -982,7 +987,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
|
||||
github.com/linxGnu/gumble v1.0.0 h1:OAJud8Hy4rmV9I5p/KTRiVpwwklMTd9Ankza3Mz7a4M=
|
||||
@@ -1027,7 +1031,6 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 h1:+/+DxvQaYifJ+grD4klzrS5y+KJXldn/2YTl5JG+vZ8=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=
|
||||
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
@@ -1090,6 +1093,7 @@ github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b h1:m74UWYy+HBs+jMFR9
|
||||
github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
|
||||
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
|
||||
github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||
@@ -1374,10 +1378,11 @@ google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
|
||||
gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
|
||||
modernc.org/b v1.0.2 h1:iPC2u39ebzq12GOC2yXT4mve0HrWcH85cz+midWjzeo=
|
||||
modernc.org/db v1.0.3 h1:apxOlWU69je04bY22OT6J0RL23mzvUy22EgTAVyw+Yg=
|
||||
|
||||
Reference in New Issue
Block a user