mirror of
https://gitee.com/johng/gf
synced 2026-07-01 19:31:23 +08:00
api swagger ui update
This commit is contained in:
4
example/httpserver/swagger/config.yaml
Normal file
4
example/httpserver/swagger/config.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
server:
|
||||
address: ":8199"
|
||||
openapiPath: "/api.json"
|
||||
swaggerPath: "/swagger"
|
||||
38
example/httpserver/swagger/main.go
Normal file
38
example/httpserver/swagger/main.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type HelloReq struct {
|
||||
g.Meta `path:"/hello" method:"get"`
|
||||
Name string `v:"required" dc:"Your name"`
|
||||
}
|
||||
type HelloRes struct {
|
||||
Reply string `dc:"Reply content"`
|
||||
}
|
||||
|
||||
type Hello struct{}
|
||||
|
||||
func (Hello) Say(ctx context.Context, req *HelloReq) (res *HelloRes, err error) {
|
||||
g.Log().Debugf(ctx, `receive say: %+v`, req)
|
||||
res = &HelloRes{
|
||||
Reply: fmt.Sprintf(`Hi %s`, req.Name),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.Use(ghttp.MiddlewareHandlerResponse)
|
||||
s.Group("/", func(group *ghttp.RouterGroup) {
|
||||
group.Bind(
|
||||
new(Hello),
|
||||
)
|
||||
})
|
||||
s.Run()
|
||||
}
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp/internal/swaggerui"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
@ -24,7 +25,6 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/intlog"
|
||||
"github.com/gogf/gf/v2/net/ghttp/internal/swaggerui"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
|
||||
@ -7,14 +7,31 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
const (
|
||||
swaggerUIDefaultURL = `https://petstore.swagger.io/v2/swagger.json`
|
||||
swaggerUITemplate = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>API Reference</title>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<redoc spec-url="https://petstore.swagger.io/v2/swagger.json"></redoc>
|
||||
<script src="redoc.standalone.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
)
|
||||
|
||||
// swaggerUI is a build-in hook handler for replace default swagger json URL to local openapi json file path.
|
||||
@ -23,17 +40,9 @@ func (s *Server) swaggerUI(r *Request) {
|
||||
if s.config.OpenApiPath == "" {
|
||||
return
|
||||
}
|
||||
var (
|
||||
indexFileName = `index.html`
|
||||
)
|
||||
if r.StaticFile != nil && r.StaticFile.File != nil && gfile.Basename(r.StaticFile.File.Name()) == indexFileName {
|
||||
if gfile.Basename(r.URL.Path) != indexFileName && r.originUrlPath[len(r.originUrlPath)-1] != '/' {
|
||||
r.Response.Header().Set("Location", r.originUrlPath+"/")
|
||||
r.Response.WriteHeader(http.StatusMovedPermanently)
|
||||
r.ExitAll()
|
||||
}
|
||||
if r.StaticFile != nil && r.StaticFile.File != nil && r.StaticFile.IsDir {
|
||||
r.Response.Write(gstr.Replace(
|
||||
string(r.StaticFile.File.Content()),
|
||||
swaggerUITemplate,
|
||||
swaggerUIDefaultURL,
|
||||
s.config.OpenApiPath,
|
||||
))
|
||||
|
||||
File diff suppressed because one or more lines are too long
9
net/ghttp/internal/swaggerui/swaggerui-redoc.go
Normal file
9
net/ghttp/internal/swaggerui/swaggerui-redoc.go
Normal file
File diff suppressed because one or more lines are too long
@ -6,6 +6,10 @@
|
||||
|
||||
// Package swaggerui provides packed swagger ui static files using resource manager.
|
||||
//
|
||||
// Files from: https://github.com/swagger-api/swagger-ui
|
||||
// Pack command: gf pack swagger-ui swaggerui-packed.go -n=swaggerui -p=/goframe/swaggerui
|
||||
// Files from:
|
||||
// https://github.com/Redocly/redoc
|
||||
// https://www.jsdelivr.com/package/npm/redoc
|
||||
//
|
||||
// Pack command:
|
||||
// gf pack redoc.standalone.js swaggerui-redoc.go -n=swaggerui -p=/goframe/swaggerui
|
||||
package swaggerui
|
||||
|
||||
@ -76,7 +76,11 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix
|
||||
intlog.Printf(context.TODO(), `exclude file path: %s`, file)
|
||||
continue
|
||||
}
|
||||
if err = zipFile(file, headerPrefix+gfile.Dir(file[len(path):]), zipWriter); err != nil {
|
||||
subFilePath := file[len(path):]
|
||||
if subFilePath != "" {
|
||||
subFilePath = gfile.Dir(subFilePath)
|
||||
}
|
||||
if err = zipFile(file, headerPrefix+subFilePath, zipWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/json"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/gvalid"
|
||||
)
|
||||
|
||||
type SchemaRefs []SchemaRef
|
||||
@ -35,6 +36,13 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap
|
||||
if err := gconv.Struct(oai.fileMapWithShortTags(tagMap), schema); err != nil {
|
||||
return nil, gerror.Wrap(err, `mapping struct tags to Schema failed`)
|
||||
}
|
||||
// Validation info to OpenAPI schema pattern.
|
||||
for _, tag := range gvalid.GetTags() {
|
||||
if validation, ok := tagMap[tag]; ok {
|
||||
schema.Pattern = validation
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
schemaRef.Value = schema
|
||||
switch oaiType {
|
||||
|
||||
@ -206,3 +206,8 @@ func parseSequenceTag(tag string) (field, rule, msg string) {
|
||||
match, _ := gregex.MatchString(`\s*((\w+)\s*@){0,1}\s*([^#]+)\s*(#\s*(.*)){0,1}\s*`, tag)
|
||||
return strings.TrimSpace(match[2]), strings.TrimSpace(match[3]), strings.TrimSpace(match[5])
|
||||
}
|
||||
|
||||
// GetTags returns the validation tags.
|
||||
func GetTags() []string {
|
||||
return structTagPriority
|
||||
}
|
||||
|
||||
@ -42,3 +42,9 @@ func Test_parseSequenceTag(t *testing.T) {
|
||||
t.Assert(msg, "")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetTags(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(structTagPriority, GetTags())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user