api-doc/swagger.go

234 lines
8.0 KiB
Go
Raw Permalink Normal View History

2024-12-24 11:18:15 +08:00
// Package api_doc ...
//
// Description : api_doc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-12-24 10:34
package api_doc
import (
"errors"
"git.zhangdeman.cn/gateway/api-doc/define"
2024-12-24 12:11:17 +08:00
"git.zhangdeman.cn/zhangdeman/consts"
2024-12-24 11:18:15 +08:00
"git.zhangdeman.cn/zhangdeman/serialize"
2024-12-24 12:11:17 +08:00
"net/http"
"strings"
2024-12-24 11:18:15 +08:00
)
// ParseSwagger2 解析swagger2.0版本文档
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:33 2024/12/24
func ParseSwagger2(docContent []byte) (*define.DocParseResult, error) {
var (
err error
swaggerDoc define.Swagger
)
if err = serialize.JSON.UnmarshalWithNumber(docContent, &swaggerDoc); nil != err {
return nil, errors.New("parse swagger json fail : " + err.Error())
}
docResult := &define.DocParseResult{
2024-12-25 14:59:14 +08:00
Domain: swaggerDoc.Host,
Title: swaggerDoc.Info.Title,
Description: swaggerDoc.Info.Description,
UriList: make([]*define.UriBaseConfig, 0),
GlobalSecurityParamList: make([]*define.ParamConfig, 0),
2024-12-24 11:18:15 +08:00
}
if docResult.UriList, err = buildUriList(&swaggerDoc); nil != err {
return nil, err
}
2024-12-25 14:59:14 +08:00
docResult.GlobalSecurityParamList = buildSwagger2GlobalSecurityParamList(&swaggerDoc)
2024-12-24 11:18:15 +08:00
return docResult, nil
}
2024-12-25 14:59:14 +08:00
// buildSwagger2GlobalSecurityParamList 构建全局安全类参数
func buildSwagger2GlobalSecurityParamList(swaggerDoc *define.Swagger) []*define.ParamConfig {
result := make([]*define.ParamConfig, 0)
for paramName, paramConfig := range swaggerDoc.SecurityDefinitions {
if len(paramConfig.In) == 0 {
continue
}
result = append(result, &define.ParamConfig{
Location: GetParamLocation(paramConfig.In).String(),
Path: paramName,
Type: GetDataType(paramConfig.Type, ""),
2024-12-25 14:59:14 +08:00
Title: paramName,
Description: paramConfig.Description,
Required: false,
})
}
return result
}
2024-12-24 11:18:15 +08:00
// 解析uri列表
func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) {
uriList := make([]*define.UriBaseConfig, 0)
for itemUri, itemUriMethodConfig := range swaggerDoc.Paths {
2024-12-24 12:11:17 +08:00
for requestMethod, methodConfig := range itemUriMethodConfig {
2024-12-24 12:33:50 +08:00
initSwagger2UriMethodConfig(requestMethod, methodConfig)
2024-12-24 12:11:17 +08:00
uriResult := &define.UriBaseConfig{
Uri: swaggerDoc.BasePath + "/" + strings.TrimLeft(itemUri, "/"),
Method: strings.ToUpper(requestMethod),
ContentType: methodConfig.Consumes,
OutputContentType: methodConfig.Produces,
2024-12-24 12:11:17 +08:00
TagList: methodConfig.Tags,
Summary: methodConfig.Summary,
Description: methodConfig.Description,
2024-12-24 12:33:50 +08:00
ParamList: buildSwagger2ParamConfig(swaggerDoc, methodConfig.Parameters),
ResultList: buildSwagger2ResultConfig(swaggerDoc, methodConfig.Responses),
2024-12-24 12:11:17 +08:00
}
uriList = append(uriList, uriResult)
}
2024-12-24 11:18:15 +08:00
}
return uriList, nil
}
2024-12-24 12:33:50 +08:00
// 初始化配置请求方法 返回类型
func initSwagger2UriMethodConfig(requestMethod string, methodConfig *define.SwaggerPathConfig) {
if len(methodConfig.Consumes) == 0 {
// 未配置请求方法, 写请求 json , 读请求 form
if strings.ToUpper(requestMethod) == http.MethodPost ||
strings.ToUpper(requestMethod) == http.MethodPut ||
strings.ToUpper(requestMethod) == http.MethodPatch ||
strings.ToUpper(requestMethod) == http.MethodDelete {
methodConfig.Consumes = []string{
consts.MimeTypeJson,
}
} else {
methodConfig.Consumes = []string{
consts.MimeTypeXWWWFormUrlencoded,
}
}
}
if len(methodConfig.Produces) == 0 {
// 未配置输出数据类型, 默认 json
methodConfig.Produces = []string{
consts.MimeTypeJson,
}
}
}
// buildSwagger2ParamConfig 构建请求参数配置
func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*define.SwaggerPathConfigParameter) []*define.ParamConfig {
res := make([]*define.ParamConfig, 0)
// 解析参数
for _, paramConfig := range paramConfigList {
if paramConfig.Name != "body" {
paramConfigBuildConfig := &define.ParamConfig{
Location: GetParamLocation(paramConfig.In).String(),
Path: paramConfig.Name,
Type: GetDataType(paramConfig.Type, paramConfig.Format),
Title: paramConfig.Name,
Description: paramConfig.Description,
Required: paramConfig.Required,
}
res = append(res, paramConfigBuildConfig)
}
if nil == paramConfig.Schema || len(paramConfig.Schema.Ref) == 0 {
continue
2024-12-24 12:33:50 +08:00
}
// 可以继续展开
requiredTable := make(map[string]bool)
for _, paramName := range swaggerDoc.Definitions[GetRealDefinitionsKey(paramConfig.Schema.Ref)].Required {
requiredTable[paramName] = true
}
for paramName, paramMoreConfig := range swaggerDoc.Definitions[GetRealDefinitionsKey(paramConfig.Schema.Ref)].Properties {
if paramConfig.Name != "body" {
paramName = paramConfig.Name + "." + paramName
}
paramConfigBuildConfig := &define.ParamConfig{
Location: GetParamLocation(paramConfig.In).String(),
Path: paramName,
Type: GetDataType(paramMoreConfig.Type, ""),
2024-12-25 12:04:30 +08:00
Title: paramName,
Description: paramMoreConfig.Description,
Required: requiredTable[paramName],
}
res = append(res, paramConfigBuildConfig)
if DataTypeIsArray(paramMoreConfig.Type) && nil != paramMoreConfig.Items && len(paramMoreConfig.Items.Ref) > 0 {
// 是数组,且每一项是对象, 继续展开
res = append(res, ExpandArrayParam(swaggerDoc, paramMoreConfig.Items.Ref, paramConfigBuildConfig.Path)...)
}
2024-12-24 12:33:50 +08:00
}
}
return res
}
2024-12-24 17:49:20 +08:00
// buildSwagger2ResultConfig 构建响应结果配置
func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, resultConfig map[string]*define.SwaggerPathConfigResponse) []*define.ResultConfig {
2024-12-24 17:49:20 +08:00
res := make([]*define.ResultConfig, 0)
if nil == resultConfig || len(resultConfig) == 0 {
return res
}
successResponseConfig := GetSuccessResponseConfig(resultConfig)
if nil == successResponseConfig {
2024-12-24 17:49:20 +08:00
return res
}
definitionsKey := ""
if swaggerDoc.Responses == nil {
definitionsKey = successResponseConfig.Schema.Ref
2024-12-24 17:49:20 +08:00
} else {
responseKey := GetRealResponseKey(successResponseConfig.Ref)
if len(responseKey) == 0 {
// 204 场景下可能没有响应body
res = append(res, &define.ResultConfig{
Location: consts.ResponseDataLocationBody.String(),
Path: consts.ResponseDataLocationBodyRoot.String(),
Type: consts.DataTypeAny.String(),
Title: "response body no content",
Description: "no content",
})
return res
}
2024-12-24 17:49:20 +08:00
ref := swaggerDoc.Responses[responseKey].Ref
if len(ref) == 0 {
if nil != swaggerDoc.Responses[responseKey].Schema {
ref = swaggerDoc.Responses[responseKey].Schema.Ref
}
}
definitionsKey = GetRealDefinitionsKey(ref)
}
if len(definitionsKey) == 0 {
// 不是引用类型, 直接定义的具体类型
responseKey := GetRealResponseKey(successResponseConfig.Ref)
responseTypeDefine := swaggerDoc.Responses[responseKey]
2024-12-25 12:04:30 +08:00
responseType := ""
schemaType := ""
if nil == responseTypeDefine.Schema {
2024-12-25 12:04:30 +08:00
// 204 等场景下可能没有响应body
responseType = consts.DataTypeAny.String()
} else {
schemaType = responseTypeDefine.Schema.Type
responseType = GetDataType(responseTypeDefine.Schema.Type, "")
}
resCfg := &define.ResultConfig{
2024-12-25 12:04:30 +08:00
Location: consts.ResponseDataLocationBody.String(),
Path: consts.ResponseDataLocationBodyRoot.String(),
Type: responseType,
Title: "response body",
Description: "response body",
}
res = append(res, resCfg)
if DataTypeIsArray(schemaType) && len(responseTypeDefine.Schema.Items.Ref) > 0 {
res = append(res, ExpandArrayResult(swaggerDoc, responseTypeDefine.Schema.Items.Ref, resCfg.Path)...)
}
} else {
responseTypeDefine := swaggerDoc.Definitions[definitionsKey]
for responseKey, responseKeyConfig := range responseTypeDefine.Properties {
res = append(res, &define.ResultConfig{
Location: consts.ResponseDataLocationBody.String(),
Path: responseKey,
Type: GetDataType(responseKeyConfig.Type, ""),
Title: responseKey,
2024-12-25 12:04:30 +08:00
Description: responseKey,
})
}
2024-12-24 17:49:20 +08:00
}
return res
2024-12-24 17:49:20 +08:00
}