mirror of
https://github.com/go-home-admin/toolset.git
synced 2026-04-23 00:27:03 +08:00
Swagger update
This commit is contained in:
+41
-14
@@ -44,6 +44,11 @@ func (SwaggerCommand) Configure() command.Configure {
|
|||||||
Description: "指定文档语言,如说明的下一行是‘// @lang:en name’则‘name’代替原说明",
|
Description: "指定文档语言,如说明的下一行是‘// @lang:en name’则‘name’代替原说明",
|
||||||
Default: "",
|
Default: "",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "host",
|
||||||
|
Description: "指定接口Host",
|
||||||
|
Default: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -55,6 +60,7 @@ func (SwaggerCommand) Execute(input command.Input) {
|
|||||||
out := input.GetOption("out")
|
out := input.GetOption("out")
|
||||||
path := input.GetOption("path")
|
path := input.GetOption("path")
|
||||||
language = input.GetOption("lang")
|
language = input.GetOption("lang")
|
||||||
|
host := input.GetOption("host")
|
||||||
|
|
||||||
swagger := openapi.Spec{
|
swagger := openapi.Spec{
|
||||||
Swagger: "2.0",
|
Swagger: "2.0",
|
||||||
@@ -70,6 +76,16 @@ func (SwaggerCommand) Execute(input command.Input) {
|
|||||||
Extensions: nil,
|
Extensions: nil,
|
||||||
GlobalOptions: nil,
|
GlobalOptions: nil,
|
||||||
}
|
}
|
||||||
|
if host != "" {
|
||||||
|
re := regexp.MustCompile(`^(https?)://(.+)`)
|
||||||
|
matches := re.FindStringSubmatch(host)
|
||||||
|
if matches != nil {
|
||||||
|
swagger.Schemes = []string{matches[1]}
|
||||||
|
swagger.Host = matches[2]
|
||||||
|
} else {
|
||||||
|
swagger.Host = host
|
||||||
|
}
|
||||||
|
}
|
||||||
if parser.DirIsExist(source) {
|
if parser.DirIsExist(source) {
|
||||||
data, _ := os.ReadFile(source)
|
data, _ := os.ReadFile(source)
|
||||||
json.Unmarshal(data, &swagger)
|
json.Unmarshal(data, &swagger)
|
||||||
@@ -77,14 +93,14 @@ func (SwaggerCommand) Execute(input command.Input) {
|
|||||||
|
|
||||||
allProtoc := parser.NewProtocParserForDir(path)
|
allProtoc := parser.NewProtocParserForDir(path)
|
||||||
for s, parsers := range allProtoc {
|
for s, parsers := range allProtoc {
|
||||||
prefix := getPrefix(path, s)
|
pkg := getPackage(path, s)
|
||||||
for _, fileParser := range parsers {
|
for _, fileParser := range parsers {
|
||||||
for _, message := range fileParser.Messages {
|
for _, message := range fileParser.Messages {
|
||||||
name, parameter := messageToSchemas(prefix, message, &swagger)
|
name, parameter := messageToSchemas(pkg, message, &swagger)
|
||||||
swagger.Definitions[defName(name)] = parameter
|
swagger.Definitions[defName(name)] = parameter
|
||||||
}
|
}
|
||||||
for _, enum := range fileParser.Enums {
|
for _, enum := range fileParser.Enums {
|
||||||
name, parameter := enumToMessage(prefix, enum)
|
name, parameter := enumToMessage(pkg, enum)
|
||||||
swagger.Definitions[defName(name)] = parameter
|
swagger.Definitions[defName(name)] = parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,11 +108,22 @@ func (SwaggerCommand) Execute(input command.Input) {
|
|||||||
}
|
}
|
||||||
// 全局定义后在生成url
|
// 全局定义后在生成url
|
||||||
for s, parsers := range allProtoc {
|
for s, parsers := range allProtoc {
|
||||||
prefix := getPrefix(path, s)
|
pkg := getPackage(path, s)
|
||||||
for _, fileParser := range parsers {
|
for _, fileParser := range parsers {
|
||||||
for _, service := range fileParser.Services {
|
for _, service := range fileParser.Services {
|
||||||
|
var prefix string
|
||||||
|
if routeGroup, ok := service.Opt["http.RouteGroup"]; ok {
|
||||||
|
prefix = "/$[" + routeGroup.Val + "]"
|
||||||
|
if routeGroup.Doc != "" {
|
||||||
|
re := regexp.MustCompile(`(?i)@prefix=(\w+)`)
|
||||||
|
match := re.FindStringSubmatch(routeGroup.Doc)
|
||||||
|
if match != nil {
|
||||||
|
prefix = "/" + match[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, rpc := range service.Rpc {
|
for _, rpc := range service.Rpc {
|
||||||
rpcToPath(prefix, rpc, &swagger, parsers, allProtoc, service.Opt)
|
rpcToPath(pkg, rpc, &swagger, parsers, allProtoc, prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +207,7 @@ func isValidHTTPStatusCode(code int) bool {
|
|||||||
return code >= 100 && code <= 599
|
return code >= 100 && code <= 599
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcToPath(pge string, service parser.ServiceRpc, swagger *openapi.Spec, nowDirProtoc []parser.ProtocFileParser, allProtoc map[string][]parser.ProtocFileParser, serviceOpt map[string]parser.Option) {
|
func rpcToPath(pge string, service parser.ServiceRpc, swagger *openapi.Spec, nowDirProtoc []parser.ProtocFileParser, allProtoc map[string][]parser.ProtocFileParser, prefix string) {
|
||||||
service.Doc = filterLanguage(service.Doc)
|
service.Doc = filterLanguage(service.Doc)
|
||||||
for _, options := range service.Opt {
|
for _, options := range service.Opt {
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
@@ -188,8 +215,8 @@ func rpcToPath(pge string, service parser.ServiceRpc, swagger *openapi.Spec, now
|
|||||||
if urlPath == "" {
|
if urlPath == "" {
|
||||||
urlPath = getUrl(service.Opt)
|
urlPath = getUrl(service.Opt)
|
||||||
}
|
}
|
||||||
if routeGroup, ok := serviceOpt["http.RouteGroup"]; ok {
|
if prefix != "" {
|
||||||
urlPath = "$[" + routeGroup.Val + "]" + urlPath
|
urlPath = prefix + urlPath
|
||||||
}
|
}
|
||||||
var path = &openapi.Path{}
|
var path = &openapi.Path{}
|
||||||
if o, ok := swagger.Paths[urlPath]; ok {
|
if o, ok := swagger.Paths[urlPath]; ok {
|
||||||
@@ -562,7 +589,7 @@ func getProtoToSwagger(t string) string {
|
|||||||
return "object"
|
return "object"
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrefix(path, s string) string {
|
func getPackage(path, s string) string {
|
||||||
got := strings.ReplaceAll(s, path, "")
|
got := strings.ReplaceAll(s, path, "")
|
||||||
got = strings.Trim(got, "/")
|
got = strings.Trim(got, "/")
|
||||||
got = strings.ReplaceAll(got, "/", ".")
|
got = strings.ReplaceAll(got, "/", ".")
|
||||||
@@ -635,12 +662,12 @@ func filterRequired(doc string) (string, bool) {
|
|||||||
return strings.Join(newArr, "\n"), isRequired
|
return strings.Join(newArr, "\n"), isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
// 仅支持string和number兼容两种写法 @example:xxx xxx 或 @example(xxx xxx)
|
// 仅支持string和number兼容两种写法 @example=xxx 或 @example(xxx xxx)
|
||||||
func filterExample(doc string, ty string) (string, interface{}) {
|
func filterExample(doc string, ty string) (string, interface{}) {
|
||||||
arr := strings.Split(doc, "\n")
|
arr := strings.Split(doc, "\n")
|
||||||
var newArr []string
|
var newArr []string
|
||||||
var example string
|
var example string
|
||||||
re := regexp.MustCompile(`(?i)\s*//\s*@example=(.*)`)
|
re := regexp.MustCompile(`(?i)\s*//\s*@example=(.*|\("*[^)]+"*)`)
|
||||||
re2 := regexp.MustCompile(`(?i)[/\s]*@example\((.*)\)\s*`)
|
re2 := regexp.MustCompile(`(?i)[/\s]*@example\((.*)\)\s*`)
|
||||||
for _, s := range arr {
|
for _, s := range arr {
|
||||||
matches := re.FindStringSubmatch(s)
|
matches := re.FindStringSubmatch(s)
|
||||||
@@ -671,7 +698,7 @@ func filterExample(doc string, ty string) (string, interface{}) {
|
|||||||
return strings.Join(newArr, "\n"), result
|
return strings.Join(newArr, "\n"), result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首行为默认说明,次行如://@lang:zh xxx 中的 xxx 将替换默认说明
|
// 首行为默认说明,次行如://@lang=zh xxx 中的 xxx 将替换默认说明
|
||||||
func filterLanguage(doc string) string {
|
func filterLanguage(doc string) string {
|
||||||
arr := strings.Split(doc, "\n")
|
arr := strings.Split(doc, "\n")
|
||||||
if len(arr) < 2 {
|
if len(arr) < 2 {
|
||||||
@@ -721,8 +748,8 @@ func parseTag(str string) string {
|
|||||||
return strings.Join(newArr, " \n")
|
return strings.Join(newArr, " \n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 例:@query=id @lang=zh @format:string @example=abc 用户ID
|
// 例:@query=id @lang=zh @format=string @example=abc 用户ID
|
||||||
// format默认为int,如format是对象或枚举,即使本地引用,也必须要加上包名,如@format:api.UserStatus
|
// format默认为int,如format是对象或枚举,即使本地引用,也必须要加上包名,如@format=api.UserStatus
|
||||||
func parseParamInPath(option parser.Option) (params openapi.Parameters) {
|
func parseParamInPath(option parser.Option) (params openapi.Parameters) {
|
||||||
re := regexp.MustCompile(`:([a-zA-Z_][a-zA-Z0-9_]*)`)
|
re := regexp.MustCompile(`:([a-zA-Z_][a-zA-Z0-9_]*)`)
|
||||||
matches := re.FindAllStringSubmatch(option.Val, -1)
|
matches := re.FindAllStringSubmatch(option.Val, -1)
|
||||||
|
|||||||
+11
-2
@@ -3,7 +3,16 @@
|
|||||||
### 2024-10-16 更新
|
### 2024-10-16 更新
|
||||||
|
|
||||||
1. post的payload统一改为application/json
|
1. post的payload统一改为application/json
|
||||||
2. 支持多语言,新增执行参数-lang=语言标识,以`//@lang=语言 说明`声明指定语言说明
|
2. 支持多语言,新增执行参数`-lang=语言标识`,以`//@lang=语言 说明`声明指定语言说明
|
||||||
3. 优化Description显示,tag换行显示,引用对象时采用本地说明
|
3. 优化Description显示,tag换行显示,引用对象时采用本地说明
|
||||||
4. 支持example定义,用`//@example=”或“//@example()`声明,前者不支持空格
|
4. 支持example定义,用`//@example=”或“//@example()`声明,前者不支持空格
|
||||||
5. 增加path的参数及说明,于请求声明上一行添加注释,例如:`option (http.Get) = "/user/:id";`,上一行添加:`// @query=id @lang=语言标识 @format=string @example=ABC 说明文本`,其中query是必须指定声明,format默认为int
|
5. 增加path的参数及说明,于请求声明上一行添加注释,例如:`option (http.Get) = "/user/:id";`,上一行添加:`// @query=id @lang=语言标识 @format=string @example=ABC 说明文本`,其中query是必须指定声明,format默认为int
|
||||||
|
|
||||||
|
### 2024-10-18 更新
|
||||||
|
|
||||||
|
1. 在路由组声明上一行加上注释`@prefix=xxx`即可指定当前protobuf文件生成的swagger的接口前缀为`xxx`,该注释仅文档使用,应与业务代码一致)
|
||||||
|
```
|
||||||
|
// @prefix=api
|
||||||
|
option (http.RouteGroup) = "api";
|
||||||
|
```
|
||||||
|
2. 新增执行参数`-host=接口host`,接口host以`http://`或`https://`开头则指定协议,只填域名则两者都支持
|
||||||
Reference in New Issue
Block a user