Skip to content

Commit 9a7eaec

Browse files
committed
integration swagger v1.0
1 parent bf1b167 commit 9a7eaec

File tree

5 files changed

+98
-23
lines changed

5 files changed

+98
-23
lines changed

README.md

+49-7
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ QQ交流群: [780385870](https://qm.qq.com/cgi-bin/qm/qr?k=xP5ZSGZaLLgJIjK0P89
3434
go get github.com/yoyofx/yoyogo
3535
```
3636
# 安装依赖 (由于某些原因国内下载不了依赖)
37-
## go version < 1.13
37+
## go version < 1.20
3838
```bash
3939
window 下在 cmd 中执行:
4040
set GO111MODULE=on
@@ -122,6 +122,7 @@ github.com/shima-park/agollo
122122
* [x] RouteData路由数据 (/api/:version/) 与 Binding的集成
123123
* [x] 路由组功能
124124
* [x] MVC默认模板功能
125+
* [X] MVC 自定义路由
125126
* [x] 路由过滤器 Filter
126127

127128
## MVC
@@ -139,7 +140,7 @@ github.com/shima-park/agollo
139140
* [X] 配置
140141
* [X] WebSocket
141142
* [X] JWT
142-
* [ ] swagger
143+
* [X] swagger
143144
* [X] GRpc
144145
* [X] Prometheus
145146

@@ -194,6 +195,26 @@ func registerEndpoints(rb router.IRouterBuilder) {
194195
Endpoints.UsePrometheus(rb)
195196
Endpoints.UsePprof(rb)
196197
Endpoints.UseJwt(rb)
198+
199+
//swagger api document
200+
endpoints.UseSwaggerDoc(rb,
201+
swagger.Info{
202+
Title: "YoyoGO 框架文档演示",
203+
Version: "v1.0.0",
204+
Description: "框架文档演示swagger文档 v1.0 [ #yoyogo](https://github.com/yoyofx/yoyogo).",
205+
TermsOfService: "https://dev.yoyogo.run",
206+
Contact: swagger.Contact{
207+
208+
Name: "yoyogo",
209+
},
210+
License: swagger.License{
211+
Name: "MIT",
212+
Url: "https://opensource.org/licenses/MIT",
213+
},
214+
},
215+
func(openapi *swagger.OpenApi) {
216+
openapi.AddSecurityBearerAuth()
217+
})
197218

198219
rb.GET("/error", func(ctx *context.HttpContext) {
199220
panic("http get error")
@@ -250,11 +271,12 @@ func NewUserController(userAction models.IUserAction) *UserController {
250271
return &UserController{userAction: userAction}
251272
}
252273

253-
// 请求对象的参数化绑定
254-
type RegiserRequest struct {
255-
mvc.RequestBody
256-
UserName string `param:"username"`
257-
Password string `param:"password"`
274+
// 请求对象的参数化绑定 , 使用 doc属性标注 支持swagger文档
275+
type RegisterRequest struct {
276+
mvc.RequestBody `route:"/api/users/register" doc:"用户注册"`
277+
UserName string `uri:"userName" doc:"用户名"`
278+
Password string `uri:"password" doc:"密码"`
279+
TestNumber uint64 `uri:"num" doc:"数字"`
258280
}
259281

260282
// Register函数自动绑定参数
@@ -268,6 +290,26 @@ func (this *UserController) GetInfo() mvc.ApiResult {
268290
return this.OK(this.userAction.Login("zhang"))
269291
}
270292

293+
// DocumentResponse custom document response , use doc tag for swagger
294+
type DocumentResponse struct {
295+
Message string `json:"message" doc:"消息"`
296+
List []DocumentDto `json:"list" doc:"文档列表"`
297+
Success bool `json:"success" doc:"是否成功"`
298+
}
299+
300+
// Swagger API 文档支持
301+
func (controller UserController) GetDocumentList(request *struct {
302+
mvc.RequestGET `route:"/v1/user/doc/list" doc:"获取全部文档列表"`
303+
}) DocumentResponse {
304+
305+
return DocumentResponse{Message: "GetDocumentList", List: []DocumentDto{
306+
{Id: 1, Name: "test1", Time: time.Now()}, {Id: 2, Name: "test2", Time: time.Now()},
307+
{Id: 3, Name: "test3", Time: time.Now()}, {Id: 4, Name: "test4", Time: time.Now()},
308+
{Id: 5, Name: "test5", Time: time.Now()}, {Id: 6, Name: "test6", Time: time.Now()},
309+
}, Success: true}
310+
}
311+
312+
271313
// Web程序的开始与停止事件
272314
func fireApplicationLifeEvent(life *abstractions.ApplicationLife) {
273315
printDataEvent := func(event abstractions.ApplicationEvent) {

README_En.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ func main() {
9393
* [X] configtion
9494
* [X] WebSocket
9595
* [X] JWT
96-
* [ ] swagger
97-
* [ ] GRpc
96+
* [X] swagger
97+
* [X] GRpc
9898
* [X] Prometheus
9999

100100

examples/simpleweb/contollers/usercontroller.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func (controller UserController) GetDocumentById(request *struct {
182182
Message("GetDocumentById").Build()
183183
}
184184

185-
// custom document response
185+
// DocumentResponse custom document response
186186
type DocumentResponse struct {
187187
Message string `json:"message" doc:"消息"`
188188
List []DocumentDto `json:"list" doc:"文档列表"`
@@ -193,11 +193,9 @@ func (controller UserController) GetDocumentList(request *struct {
193193
mvc.RequestGET `route:"/v1/user/doc/list" doc:"获取全部文档列表"`
194194
}) DocumentResponse {
195195

196-
list := []DocumentDto{
196+
return DocumentResponse{Message: "GetDocumentList", List: []DocumentDto{
197197
{Id: 1, Name: "test1", Time: time.Now()}, {Id: 2, Name: "test2", Time: time.Now()},
198198
{Id: 3, Name: "test3", Time: time.Now()}, {Id: 4, Name: "test4", Time: time.Now()},
199199
{Id: 5, Name: "test5", Time: time.Now()}, {Id: 6, Name: "test6", Time: time.Now()},
200-
}
201-
202-
return DocumentResponse{Message: "GetDocumentList", List: list, Success: true}
200+
}, Success: true}
203201
}

version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package yoyogo
22

33
const (
44
//Application Version, such as v1.x.x pre-release
5-
Version = "v1.8.8.release"
5+
Version = "v1.8.7.release"
66
//Application logo
77
//Logo = "IF8gICAgIF8gICAgICAgICAgICAgICAgICAgIF9fXyAgICAgICAgICAKKCApICAgKCApICAgICAgICAgICAgICAgICAgKCAgX2BcICAgICAgICAKYFxgXF8vJy8nXyAgICBfICAgXyAgICBfICAgfCAoIChfKSAgIF8gICAKICBgXCAvJy8nX2BcICggKSAoICkgLydfYFwgfCB8X19fICAvJ19gXCAKICAgfCB8KCAoXykgKXwgKF8pIHwoIChfKSApfCAoXywgKSggKF8pICkKICAgKF8pYFxfX18vJ2BcX18sIHxgXF9fXy8nKF9fX18vJ2BcX19fLycKICAgICAgICAgICAgICggKV98IHwgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgIGBcX19fLycgICAgICAgICAgICBMaWdodCBhbmQgZmFzdC4gIA=="
88
Logo = `

web/endpoints/swagger.go

+43-8
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ func UseSwaggerDoc(router router.IRouterBuilder, info swagger.Info, configFunc f
2323
_ = ctx.RequiredServices.GetService(&env)
2424
baseUrl := fmt.Sprintf("http://localhost:%s", env.Port)
2525
openapi := swagger.NewOpenApi(baseUrl, info)
26+
2627
configFunc(openapi)
27-
//openapi.AddSecurityBearerAuth()
28-
GetSwaggerRouteInfomation(openapi, router, env)
28+
GetSwaggerRouteInformation(openapi, router, env)
2929
ctx.JSON(200, openapi)
3030
})
3131

@@ -76,15 +76,51 @@ func UseSwaggerDoc(router router.IRouterBuilder, info swagger.Info, configFunc f
7676
})
7777
}
7878

79-
func GetSwaggerRouteInfomation(openapi *swagger.OpenApi, router router.IRouterBuilder, env *abstractions.HostEnvironment) {
79+
func GetSwaggerRouteInformation(openapi *swagger.OpenApi, router router.IRouterBuilder, env *abstractions.HostEnvironment) {
80+
// mvc routes
8081
builder := router.GetMvcBuilder()
8182
controllerList := builder.GetControllerDescriptorList()
8283
for _, controller := range controllerList {
83-
FilterValidParams(controller, openapi, env)
84+
getMvcRouters(controller, openapi, env)
85+
}
86+
87+
// default routes
88+
getEndpointRouters(openapi, router, env)
89+
}
90+
91+
func getEndpointRouters(openapi *swagger.OpenApi, router router.IRouterBuilder, env *abstractions.HostEnvironment) {
92+
// default normal route ,such as rb.POST("/info/:id", PostInfo)
93+
routerInfoList := router.GetRouteInfo()
94+
openapi.Tags = append(openapi.Tags, swagger.Tag{Name: "default", Description: fmt.Sprintf("Endpoints of the default route. (%v)", len(routerInfoList))})
95+
for idx, _ := range routerInfoList {
96+
// uri parameters
97+
pathInfo := swagger.Path{
98+
Tags: []string{"default"},
99+
Responses: map[string]swagger.ResponsesItem{},
100+
Parameters: []swagger.Parameters{}}
101+
102+
actPath := fmt.Sprintf("/%s%s", env.MetaData["server.path"], routerInfoList[idx].Path)
103+
// used regexp ,replace :id to {id}
104+
if strings.Contains(actPath, ":") {
105+
reg := regexp.MustCompile(`:([a-zA-Z0-9]+)`)
106+
matches := reg.FindAllString(actPath, -1)
107+
var params []swagger.Parameters
108+
if len(matches) > 0 {
109+
for _, match := range matches {
110+
paramName := strings.Replace(match, ":", "", -1)
111+
params = append(params, swagger.Parameters{In: "path", Name: paramName})
112+
}
113+
pathInfo.Parameters = params
114+
}
115+
actPath = reg.ReplaceAllString(actPath, "{$1}")
116+
}
117+
118+
pathInfo.Responses["200"] = swagger.ResponsesItem{Description: "OK"}
119+
openapi.Paths[actPath] = map[string]swagger.Path{strings.ToLower(routerInfoList[idx].Method): pathInfo}
84120
}
85121
}
86122

87-
func FilterValidParams(controller mvc.ControllerDescriptor, openapi *swagger.OpenApi, env *abstractions.HostEnvironment) {
123+
func getMvcRouters(controller mvc.ControllerDescriptor, openapi *swagger.OpenApi, env *abstractions.HostEnvironment) {
88124
serverPath := env.MetaData["server.path"]
89125
mvcTemplate := env.MetaData["mvc.template"]
90126
// mvc
@@ -154,9 +190,8 @@ func FilterValidParams(controller mvc.ControllerDescriptor, openapi *swagger.Ope
154190
actPath = act.Route.Template
155191
actPath = fmt.Sprintf("/%s%s", serverPath, actPath)
156192
// used regexp ,replace :id to {id}
157-
reg := regexp.MustCompile(`:[a-zA-Z0-9]+`)
158-
actPath = reg.ReplaceAllString(actPath, "{$0}")
159-
actPath = strings.ReplaceAll(actPath, ":", "")
193+
reg := regexp.MustCompile(`:([a-zA-Z0-9]+)`)
194+
actPath = reg.ReplaceAllString(actPath, "{$1}")
160195
pathInfo.Summary = pathInfo.Summary + " ( Route Attribute ) "
161196
} else {
162197
pathInfo.Summary = pathInfo.Summary + " ( MVC ) "

0 commit comments

Comments
 (0)