package middleware import ( "encoding/json" "fmt" "go-api/static" "net/http" "net/textproto" "regexp" "strings" "github.com/gin-gonic/gin" ) type SwaggerOptions struct { Root string } var regex = regexp.MustCompile(`(src|href)="./`) var specRegex = regexp.MustCompile(`url:.+`) func SwaggerSpecServe() gin.HandlerFunc { return func(c *gin.Context) { b, err := static.GetSpec() if err != nil { c.String(http.StatusNotFound, "not found") return } var j map[string]interface{} if err := json.Unmarshal(b, &j); err != nil { c.String(http.StatusInternalServerError, "internal error") return } if _, ok := j["host"]; ok { j["host"] = c.Request.Host } if xfp := c.Request.Header.Get(textproto.CanonicalMIMEHeaderKey("X-Forwarded-Proto")); xfp != "" && xfp == "https" { j["schemes"] = []string{xfp} } c.JSON(http.StatusOK, j) } } func SwaggerServe(prefix string, opts *SwaggerOptions) gin.HandlerFunc { return func(c *gin.Context) { fp := c.Request.URL.Path if prefix != "" { if !strings.HasPrefix(fp, prefix) { c.Next() return } if fp = strings.Replace(fp, prefix, "", 1); fp == "" { fp = "/" } } // end of slash replace to index.html file if strings.HasSuffix(fp, "/") { fp += "index.html" } if b, mime, err := static.GetWebFile(fp); err == nil { // 如果是 index.html 要更新內部的連結 轉換成絕對路徑 if fp == "/index.html" { replPrefix := prefix if !strings.HasSuffix(replPrefix, "/") { replPrefix += "/" } b = regex.ReplaceAll(b, []byte(fmt.Sprintf(`$1="%s`, replPrefix))) b = specRegex.ReplaceAll(b, []byte(fmt.Sprintf(`url: '%s.json',`, prefix))) } c.Writer.Header().Set(textproto.CanonicalMIMEHeaderKey("Content-Type"), mime) c.Status(http.StatusOK) c.Writer.Write(b) c.Abort() } } }