-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
171 lines (150 loc) · 5.37 KB
/
main.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package main
import (
"github.com/chenhu1001/marketool/cron"
"github.com/chenhu1001/marketool/goutils"
"github.com/chenhu1001/marketool/logging"
"github.com/chenhu1001/marketool/routes"
"github.com/chenhu1001/marketool/routes/response"
"github.com/chenhu1001/marketool/webserver"
"github.com/fsnotify/fsnotify"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"github.com/unrolled/secure"
"os"
"path"
"strings"
)
func main() {
// 初始化配置文件
InitWithConfigFile("./config.toml")
// 创建 gin app
middlewares := DefaultGinMiddlewares()
server := webserver.NewGinEngine(middlewares...)
// 启动定时任务
if viper.GetString("env") == "prod" {
cron.RunCronJobs(true)
}
// 注册路由
routes.Register(server)
if viper.GetString("server.protocol") == "https" {
server.Use(TlsHandler())
server.RunTLS(viper.GetString("server.addr"), "marketool.clang.asia_bundle.pem", "marketool.clang.asia.key")
} else {
// 运行服务
webserver.Run(server)
}
}
func TlsHandler() gin.HandlerFunc {
return func(c *gin.Context) {
secureMiddleware := secure.New(secure.Options{
SSLRedirect: true,
SSLHost: "marketool.clang.asia",
})
err := secureMiddleware.Process(c.Writer, c.Request)
// If there was an error, do not continue.
if err != nil {
return
}
c.Next()
}
}
func init() {
viper.SetDefault("app.chan_size", 50)
}
// InitWithConfigFile 根据 webserver 配置文件初始化 webserver
func InitWithConfigFile(configFile string) {
// 加载配置文件内容到 viper 中以便使用
configPath, file := path.Split(configFile)
if configPath == "" {
configPath = "."
}
ext := path.Ext(file)
configType := strings.Trim(ext, ".")
configName := strings.TrimSuffix(file, ext)
logging.Infof(nil, "load %s type config file %s from %s", configType, configName, configPath)
if err := goutils.InitViper(configPath, configName, configType, func(e fsnotify.Event) {
logging.Warn(nil, "Config file changed:"+e.Name)
logging.SetLevel(viper.GetString("logging.level"))
}); err != nil {
// 文件不存在时 1 使用默认配置,其他 err 直接 panic
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
panic(err)
}
logging.Error(nil, "Init viper error:"+err.Error())
}
// 设置 viper 中 webserver 配置项默认值
viper.SetDefault("env", "localhost")
viper.SetDefault("server.addr", ":4869")
viper.SetDefault("server.mode", gin.ReleaseMode)
viper.SetDefault("server.pprof", true)
viper.SetDefault("apidocs.title", "marketool swagger apidocs")
viper.SetDefault("apidocs.desc", "Using marketool to develop gin app on fly.")
viper.SetDefault("apidocs.host", "localhost:4869")
viper.SetDefault("apidocs.basepath", "/")
viper.SetDefault("apidocs.schemes", []string{"http"})
viper.SetDefault("basic_auth.username", "admin")
viper.SetDefault("basic_auth.password", "admin")
viper.SetDefault("app.chan_size", 50)
// 初始化 sentry 并创建 sentry 客户端
sentryDSN := viper.GetString("sentry.dsn")
if sentryDSN == "" {
sentryDSN = os.Getenv(logging.SentryDSNEnvKey)
}
sentryDebug := viper.GetBool("sentry.debug")
if viper.GetString("server.mode") == "release" {
sentryDebug = false
}
logging.Debug(nil, "Sentry use dns: "+sentryDSN)
sentry, err := logging.NewSentryClient(sentryDSN, sentryDebug)
if err != nil {
logging.Error(nil, "Sentry client create error:"+err.Error())
}
// 根据配置创建 logging 的 logger 并将 logging 的默认 logger 替换为当前创建的 logger
outputs := viper.GetStringSlice("logging.output_paths")
var lumberjackSink *logging.LumberjackSink
for _, output := range outputs {
if strings.HasPrefix(output, "logrotate://") {
filename := strings.Split(output, "://")[1]
maxAge := viper.GetInt("logging.logrotate.max_age")
maxBackups := viper.GetInt("logging.logrotate.max_backups")
maxSize := viper.GetInt("logging.logrotate.max_size")
compress := viper.GetBool("logging.logrotate.compress")
localtime := viper.GetBool("logging.logrotate.localtime")
lumberjackSink = logging.NewLumberjackSink("logrotate", filename, maxAge, maxBackups, maxSize, compress, localtime)
}
}
logger, err := logging.NewLogger(logging.Options{
Level: viper.GetString("logging.level"),
Format: viper.GetString("logging.format"),
OutputPaths: outputs,
DisableCaller: viper.GetBool("logging.disable_caller"),
DisableStacktrace: viper.GetBool("logging.disable_stacktrace"),
AtomicLevelServer: logging.AtomicLevelServerOption{
Addr: viper.GetString("logging.atomic_level_server.addr"),
Path: viper.GetString("logging.atomic_level_server.path"),
Username: viper.GetString("basic_auth.username"),
Password: viper.GetString("basic_auth.password"),
},
SentryClient: sentry,
LumberjackSink: lumberjackSink,
})
if err != nil {
logging.Error(nil, "Logger create error:"+err.Error())
} else {
logging.ReplaceLogger(logger)
}
}
// DefaultGinMiddlewares 默认的 gin server 使用的中间件列表
func DefaultGinMiddlewares() []gin.HandlerFunc {
m := []gin.HandlerFunc{
// 记录请求处理日志,最顶层执行
webserver.GinLogMiddleware(),
// 捕获 panic 保存到 context 中由 GinLogger 统一打印, panic 时返回 500 JSON
webserver.GinRecovery(response.Respond),
}
// 配置开启请求限频则添加限频中间件
if viper.GetBool("ratelimiter.enable") {
m = append(m, webserver.GinRatelimitMiddleware())
}
return m
}