From 9ce784ecad77f54387d231edb37c8dbcc3f29755 Mon Sep 17 00:00:00 2001 From: yoyofx Date: Mon, 29 Jan 2024 16:09:55 +0800 Subject: [PATCH] assemble swagger api json --- examples/simpleweb/contollers/dbcontroller.go | 4 +-- .../simpleweb/contollers/hubcontroller.go | 2 +- examples/simpleweb/contollers/sdcontroller.go | 2 +- .../simpleweb/contollers/usercontroller.go | 2 +- pkg/swagger/openapi.go | 2 ++ pkg/swagger/swagger_info.go | 13 ++++++++ web/endpoints/swagger.go | 32 +++++++++---------- web/mvc/controller_builder.go | 9 ++++-- web/mvc/controller_descriptor.go | 14 ++++++-- 9 files changed, 52 insertions(+), 28 deletions(-) diff --git a/examples/simpleweb/contollers/dbcontroller.go b/examples/simpleweb/contollers/dbcontroller.go index fd2f439d..ab9e371f 100644 --- a/examples/simpleweb/contollers/dbcontroller.go +++ b/examples/simpleweb/contollers/dbcontroller.go @@ -12,8 +12,8 @@ import ( ) type DbController struct { - mvc.ApiController - dbConfig configuration.OptionsSnapshot[models.MyConfig] + mvc.ApiController `doc:"数据库接口Controller"` + dbConfig configuration.OptionsSnapshot[models.MyConfig] } func NewDbController(snapshotOptions configuration.OptionsSnapshot[models.MyConfig]) *DbController { diff --git a/examples/simpleweb/contollers/hubcontroller.go b/examples/simpleweb/contollers/hubcontroller.go index 92d399e3..30a31419 100644 --- a/examples/simpleweb/contollers/hubcontroller.go +++ b/examples/simpleweb/contollers/hubcontroller.go @@ -13,7 +13,7 @@ import ( // websocket hub type HubController struct { - mvc.ApiController + mvc.ApiController `doc:"websocket hub controller"` hub *hubs.Hub redisClient *redisdb.RedisDataSource diff --git a/examples/simpleweb/contollers/sdcontroller.go b/examples/simpleweb/contollers/sdcontroller.go index a74f1638..fb5b6fb4 100644 --- a/examples/simpleweb/contollers/sdcontroller.go +++ b/examples/simpleweb/contollers/sdcontroller.go @@ -8,7 +8,7 @@ import ( ) type SDController struct { - mvc.ApiController + mvc.ApiController `doc:"服务发现接口Controller"` discoveryCache servicediscovery.Cache discoveryClient servicediscovery.IServiceDiscoveryClient discoverySelector servicediscovery.ISelector diff --git a/examples/simpleweb/contollers/usercontroller.go b/examples/simpleweb/contollers/usercontroller.go index e5beea2a..51d2362d 100644 --- a/examples/simpleweb/contollers/usercontroller.go +++ b/examples/simpleweb/contollers/usercontroller.go @@ -14,7 +14,7 @@ import ( ) type UserController struct { - mvc.ApiController `route:"user"` + mvc.ApiController `route:"user" doc:"用户接口Controller"` userAction models.IUserAction discoveryClient servicediscovery.IServiceDiscovery diff --git a/pkg/swagger/openapi.go b/pkg/swagger/openapi.go index ca29e214..e21df76b 100644 --- a/pkg/swagger/openapi.go +++ b/pkg/swagger/openapi.go @@ -3,5 +3,7 @@ package swagger type OpenApi struct { Openapi string `json:"openapi"` Info Info `json:"info"` + Servers []Server `json:"servers"` + Tags []Tag `json:"tags"` Paths map[string]map[string]Path `json:"paths"` } diff --git a/pkg/swagger/swagger_info.go b/pkg/swagger/swagger_info.go index af84674d..35aea3f4 100644 --- a/pkg/swagger/swagger_info.go +++ b/pkg/swagger/swagger_info.go @@ -20,3 +20,16 @@ type License struct { Name string `json:"name"` Url string `json:"url"` } + +type Server struct { + Url string `json:"url"` +} + +type Tag struct { + Name string `json:"name"` + Description string `json:"description"` + //ExternalDocs struct { + // Description string `json:"description"` + // Url string `json:"url"` + //} +} diff --git a/web/endpoints/swagger.go b/web/endpoints/swagger.go index 7b3f8728..6633c8e2 100644 --- a/web/endpoints/swagger.go +++ b/web/endpoints/swagger.go @@ -10,26 +10,27 @@ import ( "strings" ) -func GetAllController(router router.IRouterBuilder) map[string]map[string]swagger.Path { +func GetSwaggerRouteInfomation(openapi *swagger.OpenApi, router router.IRouterBuilder) { builder := router.GetMvcBuilder() controllerList := builder.GetControllerDescriptorList() - pathMap := make(map[string]map[string]swagger.Path) for _, controller := range controllerList { - FilterValidParams(controller, pathMap) + FilterValidParams(controller, openapi) } - return pathMap } -func FilterValidParams(controller mvc.ControllerDescriptor, pathMap map[string]map[string]swagger.Path) map[string]map[string]swagger.Path { +func FilterValidParams(controller mvc.ControllerDescriptor, openapi *swagger.OpenApi) { suf := len(controller.ControllerName) - 10 - basePath := controller.ControllerName[0:suf] + controllerName := controller.ControllerName[0:suf] + openapi.Tags = append(openapi.Tags, swagger.Tag{Name: controller.ControllerName, Description: controller.Descriptor}) for _, act := range controller.GetActionDescriptors() { // 遍历 action, 拼接api路径 swagger.Path - actPath := "/" + basePath + "/" + act.ActionName[len(act.ActionMethod):] + + actionName := strings.ReplaceAll(strings.ToLower(act.ActionName), act.ActionMethod, "") + actPath := "/" + controllerName + "/" + actionName pathInfoMap := make(map[string]swagger.Path) - pathMap[actPath] = pathInfoMap + openapi.Paths[actPath] = pathInfoMap pathInfo := swagger.Path{} - + pathInfo.Tags = []string{controller.ControllerName} // action params if len(act.MethodInfo.Parameters) > 0 { for _, param := range act.MethodInfo.Parameters { @@ -72,7 +73,6 @@ func FilterValidParams(controller mvc.ControllerDescriptor, pathMap map[string]m pathInfoMap[act.ActionMethod] = pathInfo } - return pathMap } func RequestBody(param reflectx.MethodParameterInfo) swagger.RequestBody { @@ -101,15 +101,13 @@ func RequestBody(param reflectx.MethodParameterInfo) swagger.RequestBody { func UseSwaggerUI(router router.IRouterBuilder, f func() swagger.Info) { xlog.GetXLogger("Endpoint").Debug("loaded swagger ui endpoint.") - openapi := swagger.OpenApi{} - openapi.Openapi = "3.0.3" + openapi := &swagger.OpenApi{ + Openapi: "3.0.3", + Paths: make(map[string]map[string]swagger.Path)} openapi.Info = f() router.GET("/swagger.json", func(ctx *context.HttpContext) { - pathMap := GetAllController(router) - openapi.Paths = pathMap - //marshal, _ := json.Marshal(&openapi) - //swaggerJson := marshal - ctx.JSON(200, openapi) //.Render(200, actionresult.Data{ContentType: "application/json; charset=utf-8", Data: []byte(swaggerJson)}) + GetSwaggerRouteInfomation(openapi, router) + ctx.JSON(200, openapi) }) router.GET("/swagger", func(ctx *context.HttpContext) { diff --git a/web/mvc/controller_builder.go b/web/mvc/controller_builder.go index 1f6e15ea..74bc56ef 100644 --- a/web/mvc/controller_builder.go +++ b/web/mvc/controller_builder.go @@ -71,10 +71,13 @@ func (builder *ControllerBuilder) AddController(controllerCtor interface{}) { controllerName, controllerType := reflectx.GetCtorFuncOutTypeName(controllerCtor) controllerName = strings.ToLower(controllerName) // Create Controller and Action descriptors - descriptor := NewControllerDescriptor(controllerName, controllerType, controllerCtor) - builder.mvcRouterHandler.ControllerDescriptors[controllerName] = descriptor + descriptor, err := NewControllerDescriptor(controllerName, controllerType, controllerCtor) logger.Debug("add mvc controller: [%s]", controllerName) - + if err != nil { + logger.Error(err.Error()) + return + } + builder.mvcRouterHandler.ControllerDescriptors[controllerName] = descriptor // add routes for action attributes controllerAttr := controllerType.Field(0).Tag.Get("route") if controllerAttr != "" { diff --git a/web/mvc/controller_descriptor.go b/web/mvc/controller_descriptor.go index ea63cd1f..b8cfec68 100644 --- a/web/mvc/controller_descriptor.go +++ b/web/mvc/controller_descriptor.go @@ -1,6 +1,7 @@ package mvc import ( + "errors" "github.com/yoyofx/yoyogo/utils" "github.com/yoyofx/yoyogo/web/context" "github.com/yoyofxteam/reflectx" @@ -11,12 +12,19 @@ import ( // ControllerDescriptor type ControllerDescriptor struct { ControllerName string + Descriptor string ControllerType interface{} // ctor func of controller actionDescriptors map[string]ActionDescriptor } // NewControllerDescriptor create new controller descriptor -func NewControllerDescriptor(name string, controllerType reflect.Type, controllerCtor interface{}) ControllerDescriptor { +func NewControllerDescriptor(name string, controllerType reflect.Type, controllerCtor interface{}) (ControllerDescriptor, error) { + + fieldApiController := controllerType.Field(0) + if fieldApiController.Name != "ApiController" { + return ControllerDescriptor{}, errors.New("controller must be embed field0 ApiController") + } + controllerDoc := fieldApiController.Tag.Get("doc") instance := reflect.New(controllerType).Interface() actionList := reflectx.GetObjectMethodInfoList(instance) @@ -25,7 +33,7 @@ func NewControllerDescriptor(name string, controllerType reflect.Type, controlle for _, action := range actionList { actionName := strings.ToLower(action.Name) - if !utils.ContainsStr([]string{"fail", "ok", "setviewengine", "view", "getname"}, actionName) { + if !utils.ContainsStr([]string{"apiresult", "fail", "ok", "setviewengine", "view", "getname"}, actionName) { actionDescriptors[actionName] = ActionDescriptor{ ActionName: action.Name, ActionMethod: getHttpMethodByActionName(actionName), @@ -34,7 +42,7 @@ func NewControllerDescriptor(name string, controllerType reflect.Type, controlle } } - return ControllerDescriptor{name, controllerCtor, actionDescriptors} + return ControllerDescriptor{name, controllerDoc, controllerCtor, actionDescriptors}, nil } // GetActionDescriptors get action descriptor list