2025-02-16 13:25:11 +08:00
|
|
|
// Package api_doc ...
|
|
|
|
//
|
|
|
|
// Description : api_doc ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 2025-02-16 13:19
|
|
|
|
package api_doc
|
|
|
|
|
|
|
|
import (
|
2025-02-16 16:43:37 +08:00
|
|
|
"embed"
|
2025-02-16 13:25:11 +08:00
|
|
|
"git.zhangdeman.cn/gateway/api-doc/define"
|
2025-02-16 16:43:37 +08:00
|
|
|
"git.zhangdeman.cn/zhangdeman/consts"
|
2025-02-16 13:25:11 +08:00
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
knife4goFiles "github.com/go-webtools/knife4go"
|
|
|
|
knife4goGin "github.com/go-webtools/knife4go/gin"
|
|
|
|
swaggerFiles "github.com/swaggo/files"
|
|
|
|
ginSwagger "github.com/swaggo/gin-swagger"
|
2025-02-16 16:43:37 +08:00
|
|
|
"net/http"
|
|
|
|
"strings"
|
2025-02-16 13:25:11 +08:00
|
|
|
)
|
|
|
|
|
2025-02-16 16:43:37 +08:00
|
|
|
//go:embed ydoc-lucky-ui/*
|
|
|
|
var ydocUIFiles embed.FS
|
|
|
|
|
2025-02-16 13:25:11 +08:00
|
|
|
// NewSwaggerUI ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 21:21 2025/2/15
|
|
|
|
func NewSwaggerUI(info *define.Info, servers []*define.ServerItem, uiTheme string) *SwaggerUI {
|
|
|
|
return &SwaggerUI{
|
|
|
|
docInstance: NewOpenapiDoc(info, servers),
|
|
|
|
uiTheme: uiTheme,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type SwaggerUI struct {
|
|
|
|
docInstance *Generate // 文档实例
|
|
|
|
uiTheme string // 文档主题, swaggerUI / knife4go, 默认 knife4go
|
2025-02-16 16:43:37 +08:00
|
|
|
router *gin.Engine
|
|
|
|
baseUri string
|
2025-02-16 13:25:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// DocInstance 文档实例
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 13:23 2025/2/16
|
|
|
|
func (su *SwaggerUI) DocInstance() *Generate {
|
|
|
|
return su.docInstance
|
|
|
|
}
|
|
|
|
|
2025-02-16 16:43:37 +08:00
|
|
|
// RegisterHandler ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 15:00 2025/2/16
|
|
|
|
func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
|
|
|
|
su.router = router
|
|
|
|
baseUri = strings.TrimRight(baseUri, "/")
|
|
|
|
if len(baseUri) == 0 {
|
|
|
|
baseUri = "/docs/swagger"
|
|
|
|
}
|
|
|
|
su.baseUri = baseUri
|
|
|
|
router.GET("/assets/*any", func(ctx *gin.Context) {
|
|
|
|
if su.uiTheme == define.SwaggerUIThemeYDocLucky {
|
|
|
|
fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, baseUri)
|
|
|
|
byteData, _ := ydocUIFiles.ReadFile(define.SwaggerUIThemeYDocLucky + fileRealPath)
|
|
|
|
uriArr := strings.Split(ctx.Request.RequestURI, ".")
|
|
|
|
contentType := "text/" + uriArr[len(uriArr)-1]
|
|
|
|
if strings.HasSuffix(ctx.Request.RequestURI, "png") {
|
|
|
|
contentType = "image/png"
|
|
|
|
}
|
|
|
|
ctx.Header("Content-Type", contentType)
|
|
|
|
ctx.String(http.StatusOK, string(byteData))
|
|
|
|
ctx.Abort()
|
|
|
|
}
|
|
|
|
ctx.AbortWithStatus(http.StatusNotFound)
|
|
|
|
})
|
|
|
|
router.GET(baseUri+"/*any", func(ctx *gin.Context) {
|
|
|
|
if ctx.Request.RequestURI == baseUri+"/doc.json" {
|
|
|
|
// 默认swagger, 通过此接口读取文档数据
|
|
|
|
ctx.JSON(http.StatusOK, su.docInstance.Doc())
|
|
|
|
ctx.Abort()
|
|
|
|
}
|
|
|
|
if ctx.Request.RequestURI == "/doc/swagger/openapi.json" {
|
|
|
|
// knife4go 文档通过此接口读取文档列表
|
|
|
|
ctx.JSON(http.StatusOK, []map[string]any{
|
|
|
|
{
|
|
|
|
"name": "服务文档",
|
|
|
|
"url": "doc.json",
|
|
|
|
"swaggerVersion": consts.SwaggerDocVersion3,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
ctx.Abort()
|
|
|
|
}
|
|
|
|
if su.uiTheme == define.SwaggerUIThemeYDocLucky {
|
|
|
|
fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, baseUri)
|
|
|
|
byteData, _ := ydocUIFiles.ReadFile(define.SwaggerUIThemeYDocLucky + fileRealPath)
|
|
|
|
if strings.HasSuffix(ctx.Request.RequestURI, "html") {
|
|
|
|
byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", baseUri))
|
|
|
|
}
|
|
|
|
uriArr := strings.Split(ctx.Request.RequestURI, ".")
|
|
|
|
contentType := "text/" + uriArr[len(uriArr)-1]
|
|
|
|
if strings.HasSuffix(ctx.Request.RequestURI, "png") {
|
|
|
|
contentType = "image/png"
|
|
|
|
} else if strings.HasSuffix(ctx.Request.RequestURI, "js") {
|
|
|
|
contentType = "application/javascript"
|
|
|
|
}
|
|
|
|
ctx.Header("Content-Type", contentType)
|
|
|
|
ctx.String(http.StatusOK, string(byteData))
|
|
|
|
ctx.Abort()
|
|
|
|
}
|
|
|
|
}, su.Handler())
|
|
|
|
router.GET("/swagger-resources", func(ctx *gin.Context) { // lucky UI获取分组信息
|
|
|
|
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域
|
|
|
|
ctx.JSON(http.StatusOK, []map[string]any{
|
|
|
|
{
|
|
|
|
"name": "服务文档",
|
|
|
|
"url": baseUri + "/doc.json",
|
|
|
|
"swaggerVersion": consts.SwaggerDocVersion3,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
// ctx.JSON(http.StatusOK, swaggerInstance.docInstance.Data())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-02-16 13:25:11 +08:00
|
|
|
// Handler 访问文档的接口处理
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 21:34 2025/2/15
|
|
|
|
func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
|
|
|
|
switch su.uiTheme {
|
|
|
|
case define.SwaggerUIThemeKnife4go:
|
|
|
|
return su.HandleKnife4goUI()
|
|
|
|
case define.SwaggerUIThemeYDocLucky:
|
2025-02-16 16:43:37 +08:00
|
|
|
// YDoc-Lucky-UI 主题处理
|
|
|
|
return su.HandleLuckyUI()
|
2025-02-16 13:25:11 +08:00
|
|
|
default:
|
|
|
|
return su.HandleSwaggerUI()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-16 16:43:37 +08:00
|
|
|
// HandleLuckyUI ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 16:04 2025/2/16
|
|
|
|
func (su *SwaggerUI) HandleLuckyUI() func(ctx *gin.Context) {
|
|
|
|
// su.router.StaticFS(su.baseUri+"/assets", http.FS(ydocUIFiles))
|
|
|
|
return func(ctx *gin.Context) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-16 13:25:11 +08:00
|
|
|
// HandleKnife4goUI ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 21:38 2025/2/15
|
|
|
|
func (su *SwaggerUI) HandleKnife4goUI() func(ctx *gin.Context) {
|
|
|
|
resetOption := func(cfg *knife4goGin.Config) {
|
|
|
|
if nil == cfg {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cfg.Title = "服务接口文档"
|
|
|
|
}
|
|
|
|
return knife4goGin.WrapHandler(knife4goFiles.Handler, resetOption)
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleSwaggerUI ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 21:41 2025/2/15
|
|
|
|
func (su *SwaggerUI) HandleSwaggerUI() func(ctx *gin.Context) {
|
|
|
|
return ginSwagger.WrapHandler(swaggerFiles.Handler)
|
|
|
|
}
|