diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..fd84126 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +**Describe the PR** +e.g. add cool parser. + +**Relation issue** +e.g. https://github.com/swaggo/gin-swagger/pull/123/files + +**Additional context** +Add any other context about the problem here. diff --git a/README.md b/README.md index 3e8e321..2efc171 100644 --- a/README.md +++ b/README.md @@ -147,5 +147,6 @@ func main() { | Option | Type | Default | Description | |--------------------------|--------|------------|---------------------------------------------------------------------------| | URL | string | "doc.json" | URL pointing to API definition | -| DeepLinking | bool | true | Swagger deeplinking configuration | +| DocExpantion | string | "list" | Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing). | +| DeepLinking | bool | true | If set to true, enables deep linking for tags and operations. See the Deep Linking documentation for more information.| | DefaultModelsExpandDepth | int | 1 | Default expansion depth for models (set to -1 completely hide the models) | diff --git a/swagger.go b/swagger.go index bed2193..7fb3462 100644 --- a/swagger.go +++ b/swagger.go @@ -4,8 +4,8 @@ import ( "html/template" "net/http" "os" + "path/filepath" "regexp" - "strings" "sync" "golang.org/x/net/webdav" @@ -19,6 +19,7 @@ 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 } @@ -29,6 +30,13 @@ func URL(url string) func(c *Config) { } } +// 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) { @@ -49,6 +57,7 @@ func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc { defaultConfig := &Config{ URL: "doc.json", DeepLinking: true, + DocExpansion: "list", DefaultModelsExpandDepth: 1, } @@ -60,52 +69,43 @@ func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc { } // CustomWrapHandler wraps `http.Handler` into `gin.HandlerFunc` -func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc { - //create a template with name +func CustomWrapHandler(config *Config, handler *webdav.Handler) gin.HandlerFunc { + var once sync.Once + + // 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)[\?|.]*`) - var locker sync.RWMutex return func(c *gin.Context) { + matches := rexp.FindStringSubmatch(c.Request.RequestURI) - type swaggerUIBundle struct { - URL string - DeepLinking bool - DefaultModelsExpandDepth int - } - - var matches []string - if matches = rexp.FindStringSubmatch(c.Request.RequestURI); len(matches) != 3 { + if len(matches) != 3 { c.Status(404) - c.Writer.Write([]byte("404 page not found")) + _, _ = c.Writer.Write([]byte("404 page not found")) return } + path := matches[2] - prefix := matches[1] + once.Do(func() { + handler.Prefix = matches[1] + }) - locker.Lock() - h.Prefix = prefix - locker.Unlock() - - if strings.HasSuffix(path, ".html") { + switch filepath.Ext(path) { + case ".html": c.Header("Content-Type", "text/html; charset=utf-8") - } else if strings.HasSuffix(path, ".css") { + case ".css": c.Header("Content-Type", "text/css; charset=utf-8") - } else if strings.HasSuffix(path, ".js") { + case ".js": c.Header("Content-Type", "application/javascript") - } else if strings.HasSuffix(path, ".json") { + case ".json": c.Header("Content-Type", "application/json; charset=utf-8") } switch path { case "index.html": - index.Execute(c.Writer, &swaggerUIBundle{ - URL: config.URL, - DeepLinking: config.DeepLinking, - DefaultModelsExpandDepth: config.DefaultModelsExpandDepth, - }) + _ = index.Execute(c.Writer, config) case "doc.json": doc, err := swag.ReadDoc() if err != nil { @@ -113,11 +113,9 @@ func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc { return } - c.Writer.Write([]byte(doc)) + _, _ = c.Writer.Write([]byte(doc)) default: - locker.RLock() - h.ServeHTTP(c.Writer, c.Request) - locker.RUnlock() + handler.ServeHTTP(c.Writer, c.Request) } } } @@ -238,6 +236,7 @@ window.onload = function() { SwaggerUIBundle.plugins.DownloadUrl ], layout: "StandaloneLayout", + docExpansion: "{{.DocExpansion}}", deepLinking: {{.DeepLinking}}, defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}} }) diff --git a/swagger_test.go b/swagger_test.go index 567fc96..aa6a0d1 100644 --- a/swagger_test.go +++ b/swagger_test.go @@ -1,13 +1,14 @@ package ginSwagger import ( - "github.com/gin-contrib/gzip" - "github.com/swaggo/swag" - "net/http/httptest" "os" + "path/filepath" "testing" + "github.com/gin-contrib/gzip" + "github.com/swaggo/swag" + "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/swaggo/gin-swagger/swaggerFiles" @@ -74,7 +75,7 @@ func TestDisablingWrapHandler(t *testing.T) { w4 := performRequest("GET", "/simple/notfound", router) assert.Equal(t, 404, w4.Code) - os.Setenv(disablingKey, "true") + _ = os.Setenv(disablingKey, "true") router.GET("/disabling/*any", DisablingWrapHandler(swaggerFiles.Handler, disablingKey)) @@ -102,7 +103,7 @@ func TestDisablingCustomWrapHandler(t *testing.T) { w1 := performRequest("GET", "/simple/index.html", router) assert.Equal(t, 200, w1.Code) - os.Setenv(disablingKey, "true") + _ = os.Setenv(disablingKey, "true") router.GET("/disabling/*any", DisablingCustomWrapHandler(&Config{}, swaggerFiles.Handler, disablingKey)) @@ -143,25 +144,63 @@ func performRequest(method, target string, router *gin.Engine) *httptest.Respons } func TestURL(t *testing.T) { - expected := "https://github.com/swaggo/http-swagger" cfg := Config{} + + expected := "https://github.com/swaggo/http-swagger" configFunc := URL(expected) configFunc(&cfg) assert.Equal(t, expected, cfg.URL) } -func TestDeepLinking(t *testing.T) { - expected := true - cfg := Config{} - configFunc := DeepLinking(expected) +func TestDocExpansion(t *testing.T) { + var cfg Config + + expected := "list" + configFunc := DocExpansion(expected) configFunc(&cfg) - assert.Equal(t, expected, cfg.DeepLinking) + assert.Equal(t, expected, cfg.DocExpansion) + + expected = "full" + configFunc = DocExpansion(expected) + configFunc(&cfg) + assert.Equal(t, expected, cfg.DocExpansion) + + expected = "none" + configFunc = DocExpansion(expected) + configFunc(&cfg) + assert.Equal(t, expected, cfg.DocExpansion) +} + +func TestDeepLinking(t *testing.T) { + var cfg Config + assert.Equal(t, false, cfg.DeepLinking) + + configFunc := DeepLinking(true) + configFunc(&cfg) + assert.Equal(t, true, cfg.DeepLinking) + + configFunc = DeepLinking(false) + configFunc(&cfg) + assert.Equal(t, false, cfg.DeepLinking) + } func TestDefaultModelsExpandDepth(t *testing.T) { + var cfg Config + + assert.Equal(t, 0, cfg.DefaultModelsExpandDepth) + expected := -1 - cfg := Config{} configFunc := DefaultModelsExpandDepth(expected) configFunc(&cfg) assert.Equal(t, expected, cfg.DefaultModelsExpandDepth) + + expected = 1 + configFunc = DefaultModelsExpandDepth(expected) + configFunc(&cfg) + assert.Equal(t, expected, cfg.DefaultModelsExpandDepth) +} + +func TestDeepLinking2(t *testing.T) { + t.Logf("extension: %s", filepath.Ext("/asas/index.html")) }