add docExpansion feature (#163)
* add docExpansion feature * add pull request template
This commit is contained in:
parent
6433b1c297
commit
b388ffa3dd
|
|
@ -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.
|
||||||
|
|
@ -147,5 +147,6 @@ func main() {
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
|--------------------------|--------|------------|---------------------------------------------------------------------------|
|
|--------------------------|--------|------------|---------------------------------------------------------------------------|
|
||||||
| URL | string | "doc.json" | URL pointing to API definition |
|
| 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) |
|
| DefaultModelsExpandDepth | int | 1 | Default expansion depth for models (set to -1 completely hide the models) |
|
||||||
|
|
|
||||||
61
swagger.go
61
swagger.go
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/net/webdav"
|
"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`.
|
//The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `doc.json`.
|
||||||
URL string
|
URL string
|
||||||
DeepLinking bool
|
DeepLinking bool
|
||||||
|
DocExpansion string
|
||||||
DefaultModelsExpandDepth int
|
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
|
// DeepLinking set the swagger deeplinking configuration
|
||||||
func DeepLinking(deepLinking bool) func(c *Config) {
|
func DeepLinking(deepLinking bool) func(c *Config) {
|
||||||
return func(c *Config) {
|
return func(c *Config) {
|
||||||
|
|
@ -49,6 +57,7 @@ func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc {
|
||||||
defaultConfig := &Config{
|
defaultConfig := &Config{
|
||||||
URL: "doc.json",
|
URL: "doc.json",
|
||||||
DeepLinking: true,
|
DeepLinking: true,
|
||||||
|
DocExpansion: "list",
|
||||||
DefaultModelsExpandDepth: 1,
|
DefaultModelsExpandDepth: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,52 +69,43 @@ func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomWrapHandler wraps `http.Handler` into `gin.HandlerFunc`
|
// CustomWrapHandler wraps `http.Handler` into `gin.HandlerFunc`
|
||||||
func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc {
|
func CustomWrapHandler(config *Config, handler *webdav.Handler) gin.HandlerFunc {
|
||||||
//create a template with name
|
var once sync.Once
|
||||||
|
|
||||||
|
// create a template with name
|
||||||
t := template.New("swagger_index.html")
|
t := template.New("swagger_index.html")
|
||||||
index, _ := t.Parse(swagger_index_templ)
|
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 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) {
|
return func(c *gin.Context) {
|
||||||
|
matches := rexp.FindStringSubmatch(c.Request.RequestURI)
|
||||||
|
|
||||||
type swaggerUIBundle struct {
|
if len(matches) != 3 {
|
||||||
URL string
|
|
||||||
DeepLinking bool
|
|
||||||
DefaultModelsExpandDepth int
|
|
||||||
}
|
|
||||||
|
|
||||||
var matches []string
|
|
||||||
if matches = rexp.FindStringSubmatch(c.Request.RequestURI); len(matches) != 3 {
|
|
||||||
c.Status(404)
|
c.Status(404)
|
||||||
c.Writer.Write([]byte("404 page not found"))
|
_, _ = c.Writer.Write([]byte("404 page not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
path := matches[2]
|
path := matches[2]
|
||||||
prefix := matches[1]
|
once.Do(func() {
|
||||||
|
handler.Prefix = matches[1]
|
||||||
|
})
|
||||||
|
|
||||||
locker.Lock()
|
switch filepath.Ext(path) {
|
||||||
h.Prefix = prefix
|
case ".html":
|
||||||
locker.Unlock()
|
|
||||||
|
|
||||||
if strings.HasSuffix(path, ".html") {
|
|
||||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
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")
|
c.Header("Content-Type", "text/css; charset=utf-8")
|
||||||
} else if strings.HasSuffix(path, ".js") {
|
case ".js":
|
||||||
c.Header("Content-Type", "application/javascript")
|
c.Header("Content-Type", "application/javascript")
|
||||||
} else if strings.HasSuffix(path, ".json") {
|
case ".json":
|
||||||
c.Header("Content-Type", "application/json; charset=utf-8")
|
c.Header("Content-Type", "application/json; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch path {
|
switch path {
|
||||||
case "index.html":
|
case "index.html":
|
||||||
index.Execute(c.Writer, &swaggerUIBundle{
|
_ = index.Execute(c.Writer, config)
|
||||||
URL: config.URL,
|
|
||||||
DeepLinking: config.DeepLinking,
|
|
||||||
DefaultModelsExpandDepth: config.DefaultModelsExpandDepth,
|
|
||||||
})
|
|
||||||
case "doc.json":
|
case "doc.json":
|
||||||
doc, err := swag.ReadDoc()
|
doc, err := swag.ReadDoc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -113,11 +113,9 @@ func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Writer.Write([]byte(doc))
|
_, _ = c.Writer.Write([]byte(doc))
|
||||||
default:
|
default:
|
||||||
locker.RLock()
|
handler.ServeHTTP(c.Writer, c.Request)
|
||||||
h.ServeHTTP(c.Writer, c.Request)
|
|
||||||
locker.RUnlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,6 +236,7 @@ window.onload = function() {
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
],
|
],
|
||||||
layout: "StandaloneLayout",
|
layout: "StandaloneLayout",
|
||||||
|
docExpansion: "{{.DocExpansion}}",
|
||||||
deepLinking: {{.DeepLinking}},
|
deepLinking: {{.DeepLinking}},
|
||||||
defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}}
|
defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
package ginSwagger
|
package ginSwagger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-contrib/gzip"
|
|
||||||
"github.com/swaggo/swag"
|
|
||||||
|
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/gzip"
|
||||||
|
"github.com/swaggo/swag"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/swaggo/gin-swagger/swaggerFiles"
|
"github.com/swaggo/gin-swagger/swaggerFiles"
|
||||||
|
|
@ -74,7 +75,7 @@ func TestDisablingWrapHandler(t *testing.T) {
|
||||||
w4 := performRequest("GET", "/simple/notfound", router)
|
w4 := performRequest("GET", "/simple/notfound", router)
|
||||||
assert.Equal(t, 404, w4.Code)
|
assert.Equal(t, 404, w4.Code)
|
||||||
|
|
||||||
os.Setenv(disablingKey, "true")
|
_ = os.Setenv(disablingKey, "true")
|
||||||
|
|
||||||
router.GET("/disabling/*any", DisablingWrapHandler(swaggerFiles.Handler, disablingKey))
|
router.GET("/disabling/*any", DisablingWrapHandler(swaggerFiles.Handler, disablingKey))
|
||||||
|
|
||||||
|
|
@ -102,7 +103,7 @@ func TestDisablingCustomWrapHandler(t *testing.T) {
|
||||||
w1 := performRequest("GET", "/simple/index.html", router)
|
w1 := performRequest("GET", "/simple/index.html", router)
|
||||||
assert.Equal(t, 200, w1.Code)
|
assert.Equal(t, 200, w1.Code)
|
||||||
|
|
||||||
os.Setenv(disablingKey, "true")
|
_ = os.Setenv(disablingKey, "true")
|
||||||
|
|
||||||
router.GET("/disabling/*any", DisablingCustomWrapHandler(&Config{}, swaggerFiles.Handler, disablingKey))
|
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) {
|
func TestURL(t *testing.T) {
|
||||||
expected := "https://github.com/swaggo/http-swagger"
|
|
||||||
cfg := Config{}
|
cfg := Config{}
|
||||||
|
|
||||||
|
expected := "https://github.com/swaggo/http-swagger"
|
||||||
configFunc := URL(expected)
|
configFunc := URL(expected)
|
||||||
configFunc(&cfg)
|
configFunc(&cfg)
|
||||||
assert.Equal(t, expected, cfg.URL)
|
assert.Equal(t, expected, cfg.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeepLinking(t *testing.T) {
|
func TestDocExpansion(t *testing.T) {
|
||||||
expected := true
|
var cfg Config
|
||||||
cfg := Config{}
|
|
||||||
configFunc := DeepLinking(expected)
|
expected := "list"
|
||||||
|
configFunc := DocExpansion(expected)
|
||||||
configFunc(&cfg)
|
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) {
|
func TestDefaultModelsExpandDepth(t *testing.T) {
|
||||||
|
var cfg Config
|
||||||
|
|
||||||
|
assert.Equal(t, 0, cfg.DefaultModelsExpandDepth)
|
||||||
|
|
||||||
expected := -1
|
expected := -1
|
||||||
cfg := Config{}
|
|
||||||
configFunc := DefaultModelsExpandDepth(expected)
|
configFunc := DefaultModelsExpandDepth(expected)
|
||||||
configFunc(&cfg)
|
configFunc(&cfg)
|
||||||
assert.Equal(t, expected, cfg.DefaultModelsExpandDepth)
|
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"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue