-
Notifications
You must be signed in to change notification settings - Fork 4
/
echo.go
152 lines (124 loc) · 3.11 KB
/
echo.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
151
152
package echox
import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"github.com/goexl/gox"
"github.com/goexl/xiren"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
// Echo 组织echo.Echo启动
type Echo struct {
*echo.Echo
options *options
}
func New(opts ...option) *Echo {
_options := defaultOptions
for _, opt := range opts {
opt.apply(_options)
}
// 创建Echo服务器
server := echo.New()
server.HideBanner = !_options.banner
// 初始化
for _, init := range _options.inits {
init(server)
}
// 数据验证
if _options.validate {
server.Validator = &validate{validate: xiren.New()}
}
// 初始化绑定
if nil != _options.binder {
server.Binder = _options.binder
}
// 处理错误
server.HTTPErrorHandler = echo.HTTPErrorHandler(_options.error)
// 初始化中间件
server.Pre(middleware.MethodOverride())
server.Pre(middleware.RemoveTrailingSlash())
// server.Use(middleware.CSRF())
server.Use(middleware.Logger())
server.Use(middleware.RequestID())
// 配置跨域
if _options.crosEnable {
cors := middleware.DefaultCORSConfig
cors.AllowMethods = append(cors.AllowMethods, string(gox.HttpMethodOptions))
cors.AllowOrigins = _options.cros.origins
cors.AllowCredentials = _options.cros.credentials
server.Use(middleware.CORSWithConfig(cors))
}
// 打印堆栈信息
// 方便调试,默认处理没有换行,很难内眼查看堆栈信息
server.Use(panicStackFunc(_options.panicStack))
// 增加自定义上下文
server.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) error {
return next(&Context{
Context: ctx,
})
}
})
return &Echo{
Echo: server,
options: _options,
}
}
func (e *Echo) Start(opts ...startOption) (err error) {
_options := defaultStartOptions()
for _, opt := range opts {
opt.applyStart(_options)
}
// 处理路由
if 0 != len(_options.routes) {
group := &Group{proxy: e.Group(e.options.context)}
for _, route := range _options.routes {
route(group)
}
}
// 在另外的协程中启动服务器,实现优雅地关闭(Graceful Shutdown)
if _options.graceful {
go func() {
err = e.graceful(_options)
}()
} else {
err = e.Echo.Start(e.options.addr)
}
return
}
func (e *Echo) Shutdown(opts ...stopOption) error {
_options := defaultStopOptions()
for _, opt := range opts {
opt.applyStop(_options)
}
ctx, cancel := context.WithTimeout(context.Background(), _options.timeout)
defer cancel()
return e.Echo.Shutdown(ctx)
}
func (e *Echo) Url(api string) (url string) {
if strings.HasPrefix(api, `/`) {
api = api[1:]
}
if `` != e.options.proxy {
url = fmt.Sprintf(`%s/%s`, e.options.proxy, api)
} else {
url = fmt.Sprintf(`%s/%s`, e.options.addr, api)
}
return
}
func (e *Echo) graceful(options *startOptions) (err error) {
if err = e.Echo.Start(e.options.addr); nil != err {
return
}
// 等待系统退出中断并响应
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), options.shutdownTimeout)
defer cancel()
err = e.Echo.Shutdown(ctx)
return
}