package ginSwagger import ( "html/template" "net/http" "os" "path/filepath" "regexp" "sync" "golang.org/x/net/webdav" "github.com/gin-gonic/gin" "github.com/swaggo/swag" ) type swaggerConfig struct { URL string DeepLinking bool DocExpansion string DefaultModelsExpandDepth int Oauth2RedirectURL template.JS } // Config stores ginSwagger configuration variables. type Config struct { //The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `doc.json`. URL string DeepLinking bool DocExpansion string DefaultModelsExpandDepth int InstanceName string } // Convert the config to a swagger one in order to fill unexposed template values. func (c Config) ToSwaggerConfig() swaggerConfig { return swaggerConfig{ URL: c.URL, DeepLinking: c.DeepLinking, DocExpansion: c.DocExpansion, DefaultModelsExpandDepth: c.DefaultModelsExpandDepth, Oauth2RedirectURL: template.JS( "`${window.location.protocol}//${window.location.host}$" + "{window.location.pathname.split('/').slice(0, window.location.pathname.split('/').length - 1).join('/')}" + "/oauth2-redirect.html`", ), } } // URL presents the url pointing to API definition (normally swagger.json or swagger.yaml). func URL(url string) func(c *Config) { return func(c *Config) { c.URL = url } } // DocExpansion list, full, none. func DocExpansion(docExpansion string) func(c *Config) { return func(c *Config) { c.DocExpansion = docExpansion } } // DeepLinking set the swagger deeplinking configuration func DeepLinking(deepLinking bool) func(c *Config) { return func(c *Config) { c.DeepLinking = deepLinking } } // DefaultModelsExpandDepth set the default expansion depth for models // (set to -1 completely hide the models). func DefaultModelsExpandDepth(depth int) func(c *Config) { return func(c *Config) { c.DefaultModelsExpandDepth = depth } } // InstanceName set the instance name that was used to generate the swagger documents. // Defaults to swag.Name ("swagger"). func InstanceName(name string) func(c *Config) { return func(c *Config) { c.InstanceName = name } } // WrapHandler wraps `http.Handler` into `gin.HandlerFunc`. func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc { defaultConfig := &Config{ URL: "doc.json", DeepLinking: true, DocExpansion: "list", DefaultModelsExpandDepth: 1, InstanceName: swag.Name, } for _, c := range confs { c(defaultConfig) } return CustomWrapHandler(defaultConfig, h) } // CustomWrapHandler wraps `http.Handler` into `gin.HandlerFunc` func CustomWrapHandler(config *Config, handler *webdav.Handler) gin.HandlerFunc { var once sync.Once if config.InstanceName == "" { config.InstanceName = swag.Name } // create a template with name t := template.New("swagger_index.html") index, _ := t.Parse(swagger_index_templ) var rexp = regexp.MustCompile(`(.*)(index\.html|doc\.json|favicon-16x16\.png|favicon-32x32\.png|/oauth2-redirect\.html|swagger-ui\.css|swagger-ui\.css\.map|swagger-ui\.js|swagger-ui\.js\.map|swagger-ui-bundle\.js|swagger-ui-bundle\.js\.map|swagger-ui-standalone-preset\.js|swagger-ui-standalone-preset\.js\.map)[\?|.]*`) return func(c *gin.Context) { matches := rexp.FindStringSubmatch(c.Request.RequestURI) if len(matches) != 3 { c.Status(http.StatusNotFound) _, _ = c.Writer.Write([]byte("404 page not found")) return } path := matches[2] once.Do(func() { handler.Prefix = matches[1] }) switch filepath.Ext(path) { case ".html": c.Header("Content-Type", "text/html; charset=utf-8") case ".css": c.Header("Content-Type", "text/css; charset=utf-8") case ".js": c.Header("Content-Type", "application/javascript") case ".png": c.Header("Content-Type", "image/png") case ".json": c.Header("Content-Type", "application/json; charset=utf-8") } switch path { case "index.html": _ = index.Execute(c.Writer, config.ToSwaggerConfig()) case "doc.json": doc, err := swag.ReadDoc(config.InstanceName) if err != nil { c.AbortWithStatus(http.StatusInternalServerError) return } _, _ = c.Writer.Write([]byte(doc)) default: handler.ServeHTTP(c.Writer, c.Request) } } } // DisablingWrapHandler turn handler off // if specified environment variable passed func DisablingWrapHandler(h *webdav.Handler, envName string) gin.HandlerFunc { eFlag := os.Getenv(envName) if eFlag != "" { return func(c *gin.Context) { // Simulate behavior when route unspecified and // return 404 HTTP code c.String(http.StatusNotFound, "") } } return WrapHandler(h) } // DisablingCustomWrapHandler turn handler off // if specified environment variable passed func DisablingCustomWrapHandler(config *Config, h *webdav.Handler, envName string) gin.HandlerFunc { eFlag := os.Getenv(envName) if eFlag != "" { return func(c *gin.Context) { // Simulate behavior when route unspecified and // return 404 HTTP code c.String(http.StatusNotFound, "") } } return CustomWrapHandler(config, h) } const swagger_index_templ = ` Swagger UI
`