#23 Fix bug of matching path for spec

master
elvinchan 2019-05-13 10:10:24 +08:00
parent 795eb4e894
commit d715040d11
9 changed files with 58 additions and 31 deletions

View File

@ -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.

View File

@ -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-TypeUI选项Scheme等。

View File

@ -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: [

View File

@ -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"))

View File

@ -13,8 +13,6 @@
},
"version": "1.0.0"
},
"host": "example.com",
"basePath": "/",
"schemes": [
"https",
"http"

View File

@ -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

23
spec.go
View File

@ -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 {

View File

@ -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/",

View File

@ -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 {