diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca22b2d..e33433d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,6 @@ jobs: fail-fast: false matrix: go: - - "1.15.x" - "1.16.x" - "1.17.x" os: diff --git a/README.md b/README.md index 17a988d..4069a81 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,16 @@ f.GET("/openapi.json", nil, f.OpenAPI(infos, "json")) ``` **NOTE**: The generator will never panic. However, it is strongly recommended to call `fizz.Errors` to retrieve and handle the errors that may have occured during the generation of the specification before starting your API. + +## Swagger UI +To serve Swagger UI for generated Open API specification, use `AddOpenApiUIHandler` method specifying the path +``` go +f.GET("/openapi.json", nil, f.OpenAPI(infos, "json")) +swagger.AddOpenApiUIHandler(f.Engine(),"swagger-ui", "/openapi.json" ) +``` +Swagger UI will be available at `/swagger-ui` using json from `/openapi.json` + + #### Servers information If the OpenAPI specification refers to an API that is not hosted on the same domain, or using a path prefix not included in the spec, you will have to declare server information. This can be achieved using the `f.Generator().SetServers` method. diff --git a/go.mod b/go.mod index b789021..5a38060 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/wI2L/fizz -go 1.12 +go 1.16 require ( github.com/Pallinder/go-randomdata v1.2.0 diff --git a/swagger/README.md b/swagger/README.md new file mode 100644 index 0000000..75ac79d --- /dev/null +++ b/swagger/README.md @@ -0,0 +1,11 @@ +# Serve Swagger UI + +## Updating the Swagger UI assets + +1. Copy all assets from [Swagger-ui repo](https://github.com/swagger-api/swagger-ui/tree/master/dist) to `swagger-ui` directory. +2. Rename `index.html` to `index.gothml` +3. In `index.gohtml` set `url` of `SwaggerUIBundle` to `{{ .specPath }}` + +Done 👍 + +Now execute tests and make sure they pass. \ No newline at end of file diff --git a/swagger/fs_wrapper.go b/swagger/fs_wrapper.go new file mode 100644 index 0000000..cc2e159 --- /dev/null +++ b/swagger/fs_wrapper.go @@ -0,0 +1,95 @@ +package swagger + +import ( + "bytes" + "html/template" + "io" + "io/fs" + "strings" + "time" +) + +type fsWrapper struct { + fs fs.FS + specPath string +} + +func newFsWrapper(fs fs.FS, specPath string) *fsWrapper { + return &fsWrapper{ + fs: fs, + specPath: specPath, + } +} + +func (f *fsWrapper) Open(name string) (fs.File, error) { + if strings.EqualFold(name, "index.html") { + tpl, err := template.ParseFS(f.fs, "index.gohtml") + if err != nil { + return nil, err + } + data := map[string]interface{}{ + "specPath": f.specPath, + } + + buf := new(bytes.Buffer) + if err = tpl.Execute(buf, data); err != nil { + return nil, err + } + + return fsWrapperFile{ + r: io.NopCloser(bytes.NewReader(buf.Bytes())), + fInfo: fileInfoMock{ + name: name, + size: int64(buf.Len()), + }, + }, nil + } + + return f.fs.Open(name) +} + +type fsWrapperFile struct { + r io.ReadCloser + fInfo fs.FileInfo +} + +func (f fsWrapperFile) Stat() (fs.FileInfo, error) { + return f.fInfo, nil +} + +func (f fsWrapperFile) Read(bytes []byte) (int, error) { + return f.r.Read(bytes) +} + +func (f fsWrapperFile) Close() error { + return f.r.Close() +} + +type fileInfoMock struct { + name string + size int64 +} + +func (f fileInfoMock) Name() string { + return f.name +} + +func (f fileInfoMock) Size() int64 { + return f.size +} + +func (f fileInfoMock) Mode() fs.FileMode { + return fs.FileMode(0) +} + +func (f fileInfoMock) ModTime() time.Time { + return time.Now() +} + +func (f fileInfoMock) IsDir() bool { + return false +} + +func (f fileInfoMock) Sys() interface{} { + panic("implement me") +} diff --git a/swagger/swagger-ui/favicon-16x16.png b/swagger/swagger-ui/favicon-16x16.png new file mode 100644 index 0000000..8b194e6 Binary files /dev/null and b/swagger/swagger-ui/favicon-16x16.png differ diff --git a/swagger/swagger-ui/favicon-32x32.png b/swagger/swagger-ui/favicon-32x32.png new file mode 100644 index 0000000..249737f Binary files /dev/null and b/swagger/swagger-ui/favicon-32x32.png differ diff --git a/swagger/swagger-ui/index.gohtml b/swagger/swagger-ui/index.gohtml new file mode 100644 index 0000000..15cc337 --- /dev/null +++ b/swagger/swagger-ui/index.gohtml @@ -0,0 +1,60 @@ + + + +
+ +