diff --git a/README.md b/README.md index 3bba20e..159bd2c 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,16 @@ import ( // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host petstore.swagger.io -// @BasePath /v2 +// @BasePath /api/v2 func main() { r := gin.New() - url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") // The url pointing to API definition - r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) + swaggerBase := ginSwagger.SwaggerBase("docs/") // default `swagger/` + specFileName := ginSwagger.SpecFileName("swagger.json") // default `doc.json` + + apiGroup := r.Group("/api/v2") + // apiGroup.GET("/ping", api.GetPing) + apiGroup.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, swaggerBase, specFileName)) r.Run() } diff --git a/swagger.go b/swagger.go index 445ecbc..4039029 100644 --- a/swagger.go +++ b/swagger.go @@ -3,6 +3,7 @@ package ginSwagger import ( "html/template" "os" + "path/filepath" "regexp" "strings" @@ -15,20 +16,29 @@ import ( // 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 + SpecFileName string + SwaggerBase string } -// URL presents the url pointing to API definition (normally swagger.json or swagger.yaml). -func URL(url string) func(c *Config) { +// SwaggerBase sets the subpath of swagger router. Default is `swagger/`. +func SwaggerBase(swaggerBase string) func(c *Config) { return func(c *Config) { - c.URL = url + c.SwaggerBase = swaggerBase + } +} + +// SpecFileName sets name of API definition (normally swagger.json or swagger.yaml). +func SpecFileName(specFileName string) func(c *Config) { + return func(c *Config) { + c.SpecFileName = specFileName } } // WrapHandler wraps `http.Handler` into `gin.HandlerFunc`. func WrapHandler(h *webdav.Handler, confs ...func(c *Config)) gin.HandlerFunc { defaultConfig := &Config{ - URL: "doc.json", + SpecFileName: "doc.json", + SwaggerBase: "swagger/", } for _, c := range confs { @@ -43,13 +53,20 @@ func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc { //create a template with name t := template.New("swagger_index.html") index, _ := t.Parse(swagger_index_templ) + specFileName := config.SpecFileName - 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)[\?|.]*`) + if specFileName == "" { + specFileName = "doc.json" + } + + specRegexStr := strings.ReplaceAll(specFileName, ".", "\\.") + var rexp = regexp.MustCompile(`(.*)(index\.html|` + specRegexStr + `|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) { type swaggerUIBundle struct { - URL string + URL string + Oauth2RedirectURL string } var matches []string @@ -75,9 +92,10 @@ func CustomWrapHandler(config *Config, h *webdav.Handler) gin.HandlerFunc { switch path { case "index.html": index.Execute(c.Writer, &swaggerUIBundle{ - URL: config.URL, + URL: filepath.Join(config.SwaggerBase, specFileName), + Oauth2RedirectURL: filepath.Join(config.SwaggerBase, "oauth2-redirect.html"), }) - case "doc.json": + case specFileName: doc, err := swag.ReadDoc() if err != nil { panic(err) @@ -197,7 +215,8 @@ window.onload = function() { const ui = SwaggerUIBundle({ url: "{{.URL}}", dom_id: '#swagger-ui', - validatorUrl: null, + validatorUrl: null, + oauth2RedirectUrl: "{{.Oauth2RedirectURL}}", presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset diff --git a/swagger_test.go b/swagger_test.go index 5fcb40d..3ddc419 100644 --- a/swagger_test.go +++ b/swagger_test.go @@ -1,11 +1,12 @@ package ginSwagger import ( - "github.com/gin-contrib/gzip" "net/http/httptest" "os" "testing" + "github.com/gin-contrib/gzip" + "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/swaggo/gin-swagger/swaggerFiles" @@ -23,7 +24,7 @@ func TestWrapHandler(t *testing.T) { assert.Equal(t, 200, w1.Code) } -func TestWrapCustomHandler(t *testing.T) { +func TestCustomWrapHandler(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() @@ -38,8 +39,11 @@ func TestWrapCustomHandler(t *testing.T) { w3 := performRequest("GET", "/favicon-16x16.png", router) assert.Equal(t, 200, w3.Code) - w4 := performRequest("GET", "/notfound", router) - assert.Equal(t, 404, w4.Code) + w4 := performRequest("GET", "/oauth2-redirect.html", router) + assert.Equal(t, 200, w4.Code) + + w5 := performRequest("GET", "/notfound", router) + assert.Equal(t, 404, w5.Code) } func TestDisablingWrapHandler(t *testing.T) { @@ -59,8 +63,11 @@ func TestDisablingWrapHandler(t *testing.T) { w3 := performRequest("GET", "/simple/favicon-16x16.png", router) assert.Equal(t, 200, w3.Code) - w4 := performRequest("GET", "/simple/notfound", router) - assert.Equal(t, 404, w4.Code) + w4 := performRequest("GET", "/simple/oauth2-redirect.html", router) + assert.Equal(t, 200, w4.Code) + + w5 := performRequest("GET", "/simple/notfound", router) + assert.Equal(t, 404, w5.Code) os.Setenv(disablingKey, "true") @@ -75,8 +82,11 @@ func TestDisablingWrapHandler(t *testing.T) { w33 := performRequest("GET", "/disabling/favicon-16x16.png", router) assert.Equal(t, 404, w33.Code) - w44 := performRequest("GET", "/disabling/notfound", router) + w44 := performRequest("GET", "/disabling/oauth2-redirect.html", router) assert.Equal(t, 404, w44.Code) + + w55 := performRequest("GET", "/disabling/notfound", router) + assert.Equal(t, 404, w55.Code) } func TestDisablingCustomWrapHandler(t *testing.T) {