diff --git a/README.md b/README.md index aa1c61b..64d826c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ import ( func main() { // ApiRoot with Echo instance - r := echoswagger.New(echo.New(), "doc/", nil) + r := echoswagger.New(echo.New(), "/doc", nil) // Routes with parameters & responses r.POST("/", createUser). @@ -56,7 +56,7 @@ func createUser(c echo.Context) error { ## Usage #### Create a `ApiRoot` with `New()`, which is a wrapper of `echo.New()` ``` -r := echoswagger.New(echo.New(), "doc/", nil) +r := echoswagger.New(echo.New(), "/doc", nil) ``` You can use the result `ApiRoot` instance to: - Setup Security definitions, request/response Content-Types, UI options, Scheme, etc. diff --git a/README_zh-CN.md b/README_zh-CN.md index 6729e9e..ce5e268 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -31,7 +31,7 @@ import ( func main() { // ApiRoot with Echo instance - r := echoswagger.New(echo.New(), "doc/", nil) + r := echoswagger.New(echo.New(), "/doc", nil) // Routes with parameters & responses r.POST("/", createUser). @@ -56,7 +56,7 @@ func createUser(c echo.Context) error { ## 用法 #### 用`New()`创建`ApiRoot`,此方法是对`echo.New()`方法的封装 ``` -r := echoswagger.New(echo.New(), "/v1", "doc/", nil) +r := echoswagger.New(echo.New(), "/doc", nil) ``` 你可以用这个`ApiRoot`来: - 设置Security定义, 请求/响应Content-Type,UI选项,Scheme等。 diff --git a/assets.go b/assets.go index 0dc4bab..9342897 100644 --- a/assets.go +++ b/assets.go @@ -51,11 +51,23 @@ const SwaggerUIContent = `{{define "swagger"}} if (!window.location.pathname.endsWith("/")) { specPath = "/" + specPath } - var spec = "{{.spec}}" + var specStr = "{{.spec}}" + var spec = specStr ? JSON.parse(specStr) : undefined + if (spec) { + spec.host = window.location.host + var docPath = "{{.docPath}}" + var basePath = window.location.pathname + if (!docPath.endsWith("/")) { docPath += "/" } + if (!basePath.endsWith("/")) { basePath += "/" } + if (basePath.endsWith(docPath)) { + basePath = basePath.slice(0, -docPath.length) + } + spec.basePath = basePath + } // Build a system const ui = SwaggerUIBundle({ url: window.location.origin+window.location.pathname+specPath, - spec: spec ? JSON.parse(spec) : undefined, + spec: spec, dom_id: '#swagger-ui', deepLinking: true, presets: [ diff --git a/examples/main.go b/examples/main.go index b918346..237645b 100644 --- a/examples/main.go +++ b/examples/main.go @@ -36,7 +36,7 @@ func initServer() echoswagger.ApiRoot { se.SetExternalDocs("Find out more about Swagger", "http://swagger.io"). SetResponseContentType("application/xml", "application/json"). - SetUI(echoswagger.UISetting{HideTop: true}). + SetUI(echoswagger.UISetting{DetachSpec: true, HideTop: true}). SetScheme("https", "http") PetController{}.Init(se.Group("pet", "/pet")) diff --git a/examples/swagger.json b/examples/swagger.json index 60053bc..7b92161 100644 --- a/examples/swagger.json +++ b/examples/swagger.json @@ -13,8 +13,6 @@ }, "version": "1.0.0" }, - "host": "example.com", - "basePath": "/", "schemes": [ "https", "http" diff --git a/internal.go b/internal.go index a1eb833..e9ee7f6 100644 --- a/internal.go +++ b/internal.go @@ -59,6 +59,7 @@ func (r *Root) docHandler(docPath string) echo.HandlerFunc { return c.String(http.StatusInternalServerError, err.Error()) } params["spec"] = string(b) + params["docPath"] = docPath params["hideTop"] = true } else { params["hideTop"] = r.ui.HideTop diff --git a/spec.go b/spec.go index 1711942..abcaf49 100644 --- a/spec.go +++ b/spec.go @@ -21,11 +21,20 @@ func (r *Root) specHandler(docPath string) echo.HandlerFunc { if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } + var basePath string + if uri, err := url.ParseRequestURI(c.Request().Referer()); err == nil { + basePath = trimSuffixSlash(uri.Path, docPath) + spec.Host = uri.Host + } else { + basePath = trimSuffixSlash(c.Request().URL.Path, connectPath(docPath, SpecName)) + spec.Host = c.Request().Host + } + spec.BasePath = basePath return c.JSON(http.StatusOK, spec) } } -// Generate swagger spec data +// Generate swagger spec data, without host & basePath info func (r *Root) GetSpec(c echo.Context, docPath string) (Swagger, error) { r.once.Do(func() { r.err = r.genSpec(c) @@ -34,17 +43,7 @@ func (r *Root) GetSpec(c echo.Context, docPath string) (Swagger, error) { if r.err != nil { return Swagger{}, r.err } - swagger := *r.spec - var basePath string - if uri, err := url.ParseRequestURI(c.Request().Referer()); err == nil { - basePath = trimSuffixSlash(uri.Path, docPath) - swagger.Host = uri.Host - } else { - basePath = trimSuffixSlash(c.Request().URL.Path, connectPath(docPath, SpecName)) - swagger.Host = c.Request().Host - } - swagger.BasePath = connectPath(basePath) - return swagger, nil + return *r.spec, nil } func (r *Root) genSpec(c echo.Context) error { diff --git a/spec_test.go b/spec_test.go index f5cd800..d44a54a 100644 --- a/spec_test.go +++ b/spec_test.go @@ -20,7 +20,7 @@ func TestSpec(t *testing.T) { req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","basePath":"/","paths":{}}` + j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","paths":{}}` if assert.NoError(t, r.(*Root).specHandler("/doc/")(c)) { assert.Equal(t, http.StatusOK, rec.Code) assert.JSONEq(t, j, rec.Body.String()) @@ -33,7 +33,22 @@ func TestSpec(t *testing.T) { req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","basePath":"/","paths":{}}` + j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"paths":{}}` + s, err := r.(*Root).GetSpec(c, "/doc/") + assert.Nil(t, err) + rs, err := json.Marshal(s) + assert.Nil(t, err) + assert.JSONEq(t, j, string(rs)) + }) + + t.Run("BasicIntegrated", func(t *testing.T) { + r := prepareApiRoot() + r.SetUI(UISetting{DetachSpec: false}) + e := r.(*Root).echo + req := httptest.NewRequest(echo.GET, "/doc", nil) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"paths":{}}` s, err := r.(*Root).GetSpec(c, "/doc/") assert.Nil(t, err) rs, err := json.Marshal(s) @@ -83,7 +98,7 @@ func TestSpec(t *testing.T) { req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","basePath":"/","paths":{"/ping":{"get":{"responses":{"default":{"description":"successful operation"}}}},"/users/{id}":{"delete":{"tags":["Users"],"responses":{"default":{"description":"successful operation"}}}}},"tags":[{"name":"Users"}]}` + j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","paths":{"/ping":{"get":{"responses":{"default":{"description":"successful operation"}}}},"/users/{id}":{"delete":{"tags":["Users"],"responses":{"default":{"description":"successful operation"}}}}},"tags":[{"name":"Users"}]}` if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) { assert.Equal(t, http.StatusOK, rec.Code) assert.JSONEq(t, j, rec.Body.String()) @@ -105,21 +120,21 @@ func TestReferer(t *testing.T) { host: "localhost:1323", docPath: "/doc", name: "A", - basePath: "/", + basePath: "", }, { referer: "http://localhost:1323/doc", host: "localhost:1323", docPath: "/doc/", name: "B", - basePath: "/", + basePath: "", }, { referer: "http://localhost:1323/doc/", host: "localhost:1323", docPath: "/doc", name: "C", - basePath: "/", + basePath: "", }, { referer: "http://localhost:1323/api/v1/doc", @@ -133,14 +148,14 @@ func TestReferer(t *testing.T) { host: "127.0.0.1", docPath: "/doc", name: "E", - basePath: "/", + basePath: "", }, { referer: "http://user:pass@github.com", host: "github.com", docPath: "/", name: "F", - basePath: "/", + basePath: "", }, { referer: "https://www.github.com/v1/docs/?q=1", @@ -154,7 +169,7 @@ func TestReferer(t *testing.T) { host: "www.github.com", docPath: "", name: "H", - basePath: "/", + basePath: "", }, { referer: "https://www.github.com/", diff --git a/wrapper_test.go b/wrapper_test.go index 72fa846..aadc494 100644 --- a/wrapper_test.go +++ b/wrapper_test.go @@ -12,7 +12,9 @@ import ( ) func prepareApiRoot() ApiRoot { - return New(echo.New(), "doc/", nil) + r := New(echo.New(), "doc/", nil) + r.SetUI(UISetting{DetachSpec: true}) + return r } func prepareApiGroup() ApiGroup {