// Package router ... // // Description : api_doc ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2025-02-16 13:19 package router import ( "embed" "net/http" "path/filepath" "strings" "git.zhangdeman.cn/zhangdeman/consts" "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" ) //go:embed theme/* var ThemeFiles embed.FS // NewSwaggerUI ... func NewSwaggerUI(docTitle string, docBaseUri string, uiTheme consts.SwaggerUITheme) *SwaggerUI { return &SwaggerUI{ baseUri: docBaseUri, docTitle: docTitle, uiTheme: uiTheme, } } type SwaggerUI struct { baseUri string docTitle string uiTheme consts.SwaggerUITheme // 文档主题, swaggerUI / knife4go, 默认 knife4go } // Handler 访问文档的接口处理 func (su *SwaggerUI) Handler() func(ctx *gin.Context) { switch su.uiTheme { case consts.SwaggerUIThemeKnife4go: return su.HandleKnife4goUI() case consts.SwaggerUIThemeDefault: return su.HandleSwaggerDefaultUI() case consts.SwaggerUIThemeYDocLucky, consts.SwaggerUIThemeElements, consts.SwaggerUIThemeSwaggerUI, consts.SwaggerUIThemeScalar, consts.SwaggerUIThemeRedocFree, consts.SwaggerUIThemeRapiDoc: // YDoc-Lucky-UI 主题处理 return su.renderWebPage(su.uiTheme) default: return su.HandleSwaggerDefaultUI() } } func (su *SwaggerUI) renderWebPage(themeUI consts.SwaggerUITheme) func(ctx *gin.Context) { return func(ctx *gin.Context) { fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, su.baseUri) byteData, _ := ThemeFiles.ReadFile(filepath.Join("theme", themeUI.String(), fileRealPath)) if strings.Contains(ctx.Request.RequestURI, ".html") { byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", su.baseUri)) byteData = []byte(strings.ReplaceAll(string(byteData), "{{DOC_TITLE}}", su.docTitle)) byteData = []byte(strings.ReplaceAll(string(byteData), "{{DOC_PATH}}", "doc.json")) ctx.Header(consts.HeaderKeyContentType.String(), "text/html; charset=utf-8") ctx.String(http.StatusOK, string(byteData)) ctx.Abort() return } uriArr := strings.Split(ctx.Request.RequestURI, ".") contentType := "text/" + uriArr[len(uriArr)-1] if strings.HasSuffix(ctx.Request.RequestURI, "png") { contentType = consts.MimeTypeImagePng } else if strings.HasSuffix(ctx.Request.RequestURI, "js") { contentType = "application/javascript" } ctx.Header(consts.HeaderKeyContentType.String(), contentType) ctx.String(http.StatusOK, string(byteData)) ctx.Abort() } } // HandleKnife4goUI ... 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) } // HandleSwaggerDefaultUI ... func (su *SwaggerUI) HandleSwaggerDefaultUI() func(ctx *gin.Context) { return ginSwagger.WrapHandler(swaggerFiles.Handler) }