This repository has been archived by the owner on Nov 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathswagger.go
150 lines (139 loc) · 4.78 KB
/
swagger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Package swagger provides swagger UI resource files for swagger API service.
//
// Should be used with gf cli tool:
// gf pack public ./public-packed.go -p=swagger -y
//
package swagger
import (
"fmt"
"net/http"
"time"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)
// Swagger is the struct for swagger feature management.
type Swagger struct {
Info SwaggerInfo // Swagger information.
Schemes []string // Supported schemes of the swagger API like "http", "https".
Host string // The host of the swagger APi like "127.0.0.1", "www.mydomain.com"
BasicPath string // The URI for the swagger API like "/", "v1", "v2".
BasicAuthUser string `c:"user"` // HTTP basic authentication username.
BasicAuthPass string `c:"pass"` // HTTP basic authentication password.
}
// SwaggerInfo is the information field for swagger.
type SwaggerInfo struct {
Title string // Title of the swagger API.
Version string // Version of the swagger API.
TermsOfService string // As the attribute name.
Description string // Detail description of the swagger API.
}
const (
Name = "gf-swagger"
Author = "[email protected]"
Version = "v1.2.0"
Description = "gf-swagger provides swagger API document feature for GoFrame project. https://github.com/gogf/gf-swagger"
MaxAuthAttempts = 10 // Max authentication count for failure try.
AuthFailedInterval = time.Minute // Authentication retry interval after last failed.
)
// Name returns the name of the plugin.
func (swagger *Swagger) Name() string {
return Name
}
// Author returns the author of the plugin.
func (swagger *Swagger) Author() string {
return Author
}
// Version returns the version of the plugin.
func (swagger *Swagger) Version() string {
return Version
}
// Description returns the description of the plugin.
func (swagger *Swagger) Description() string {
return Description
}
// Install installs the swagger to server as a plugin.
// It implements the interface ghttp.Plugin.
func (swagger *Swagger) Install(s *ghttp.Server) error {
var ctx = gctx.New()
// Retrieve the configuration map and assign it to swagger object.
m := g.Cfg().MustGet(ctx, "swagger").Map()
if m != nil {
if err := gconv.Struct(m, swagger); err != nil {
s.Logger().Fatal(ctx, err)
}
}
// The swagger resource files are served as static file service.
s.AddStaticPath("/swagger", "swagger")
// It here uses HOOK feature handling basic auth authentication and swagger.json modification.
s.Group("/swagger", func(group *ghttp.RouterGroup) {
group.Hook("/*", ghttp.HookBeforeServe, func(r *ghttp.Request) {
if swagger.BasicAuthUser != "" {
// Authentication security checks.
var (
authCacheKey = fmt.Sprintf(`swagger_auth_failed_%s`, r.GetClientIp())
authCount = gcache.MustGet(ctx, authCacheKey).Int()
)
if authCount > MaxAuthAttempts {
r.Response.WriteStatus(
http.StatusForbidden,
"max authentication count exceeds, please try again in one minute!",
)
r.ExitAll()
}
// Basic authentication.
if !r.BasicAuth(swagger.BasicAuthUser, swagger.BasicAuthPass) {
_ = gcache.Set(ctx, authCacheKey, authCount+1, AuthFailedInterval)
r.ExitAll()
}
}
// Modify the swagger.json.
if r.StaticFile != nil && gfile.Basename(r.URL.Path) == "swagger.json" {
var content []byte
if r.StaticFile.File != nil {
content = r.StaticFile.File.Content()
} else {
content = gfile.GetBytes(r.StaticFile.Path)
}
j, _ := gjson.LoadContent(content)
if swagger.Host != "" {
j.Set("host", swagger.Host)
} else if !j.Contains("host") || gstr.Contains(j.Get("host").String(), "{") {
j.Set("host", r.Host)
}
if swagger.BasicPath != "" {
j.Set("basePath", swagger.BasicPath)
} else if !j.Contains("basePath") || gstr.Contains(j.Get("basePath").String(), "{") {
j.Set("basePath", "/")
}
if len(swagger.Schemes) > 0 {
j.Set("schemes", swagger.Schemes)
}
if swagger.Info.Title != "" {
j.Set("info.title", swagger.Info.Title)
}
if swagger.Info.Version != "" {
j.Set("info.version", swagger.Info.Version)
}
if swagger.Info.TermsOfService != "" {
j.Set("info.termsOfService", swagger.Info.TermsOfService)
}
if swagger.Info.Description != "" {
j.Set("info.description", swagger.Info.Description)
}
r.Response.WriteJson(j.MustToJson())
r.ExitAll()
}
})
})
return nil
}
// Remove uninstalls swagger feature from server.
func (swagger *Swagger) Remove() error {
return nil
}