Repository navigation
Expand file tree
/
Copy pathengine.go
More file actions
144 lines (117 loc) · 3.61 KB
/
Copy pathengine.go
File metadata and controls
144 lines (117 loc) · 3.61 KB
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
package sgin
import (
"errors"
"net"
"net/http"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
ut "github.com/go-playground/universal-translator"
"golang.org/x/text/language"
)
const EngineKey = "_baa/sgin/engine"
type Engine struct {
Router
cfg Config
engine *gin.Engine
languageMatcher language.Matcher
translator *ut.UniversalTranslator
defaultLang language.Tag
}
type Config struct {
Mode string // gin.DebugMode | gin.ReleaseMode | gin.TestMode
TrustedProxies []string // gin.SetTrustedProxies
Recovery func(c *Ctx, out, s string) // 回调 [带颜色的控制台输出] 和 [结构化 JSON 日志]
ErrorHandler func(c *Ctx, err error) error
Logger func(c *Ctx, out string, s string) // 回调 [带颜色的控制台输出] 和 [结构化 JSON 日志]
Cors func(*cors.Config) // 默认配置 cors.DefaultConfig()
OpenAPI *API
Locales []language.Tag // 绑定验证错误所使用的多语言支持
}
// DefaultErrorHandler 默认的错误处理器
func DefaultErrorHandler(c *Ctx, err error) error {
code := http.StatusInternalServerError
var e *Error
if errors.As(err, &e) && e.Code > 0 { // 如果是 *Error 错误
code = e.Code
} else if stc := c.StatusCode(); stc != 200 && stc != 0 {
code = stc
}
return c.Content(MIMETextPlain).Status(code).Send(err.Error())
}
// DefaultConfig 默认配置
func DefaultConfig(config ...Config) (cfg Config) {
if len(config) > 0 {
cfg = config[0]
}
if cfg.ErrorHandler == nil {
cfg.ErrorHandler = DefaultErrorHandler
}
return cfg
}
func New(config ...Config) *Engine {
cfg := DefaultConfig(config...)
gin.SetMode(cfg.Mode)
e := &Engine{engine: gin.New(), cfg: cfg}
e.Router = Router{
i: e.engine,
e: e,
base: "/",
api: cfg.OpenAPI,
op: Operation{Responses: map[string]*ResponseBody{}},
}
e.useMiddleware()
// gin.engine 配置
if err := e.engine.SetTrustedProxies(cfg.TrustedProxies); err != nil {
debugWarning(err.Error())
}
// OpenAPI 文档中间件
if cfg.OpenAPI != nil && cfg.Mode != gin.ReleaseMode {
e.GET("/openapi.yaml", He(func(c *Ctx) error {
if specYAML, err := cfg.OpenAPI.YAML(); err == nil {
return c.Content(MIMEYAML).Send(string(specYAML))
}
return c.Send(ErrInternalServerError())
}), APIHidden)
e.GET("/docs", He(func(c *Ctx) error {
return c.Content(MIMETextHTML).Send(DocsHTML)
}), APIHidden)
debugInfo("OpenAPI 已开启,访问 /docs 或 /openapi.yaml 查看文档。")
}
return e
}
// Routes 返回注册的路由信息切片
func (e *Engine) Routes() gin.RoutesInfo {
return e.engine.Routes()
}
// Run 将路由器连接到 http.Server 并开始监听和提供 HTTP[S] 请求
//
// 提供 cert 和 key 文件路径作为 certfile 参数,可开启 HTTPS 服务。
func (e *Engine) Run(addr string, certfile ...string) (err error) {
if len(certfile) > 0 {
return e.engine.RunTLS(addr, certfile[0], certfile[1])
}
return e.engine.Run(addr)
}
// RunListener 将路由器连接到 http.Server, 并开始通过指定的 listener 监听和提供 HTTP 请求。
func (e *Engine) RunListener(listener net.Listener) (err error) {
return e.engine.RunListener(listener)
}
func (e *Engine) Gin() *gin.Engine {
return e.engine
}
func (e *Engine) useMiddleware() {
cfg := e.cfg
e.Use(func(c *gin.Context) {
c.Set(EngineKey, e)
c.Next()
})
e.Use(Recovery, Logger)
if tr := useTranslator(e); tr != nil {
e.Use(tr) // 注册校验翻译器
}
if cfg.Cors != nil {
corsCfg := cors.DefaultConfig()
cfg.Cors(&corsCfg)
e.Use(cors.New(corsCfg))
}
}