161 lines
4.1 KiB
Go
161 lines
4.1 KiB
Go
package routes
|
||
|
||
import (
|
||
"context"
|
||
"dashboard/logger"
|
||
"dashboard/settings"
|
||
"errors"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
"github.com/gin-contrib/cors"
|
||
"github.com/gin-contrib/pprof"
|
||
"github.com/gin-gonic/gin"
|
||
"go.uber.org/zap"
|
||
"golang.org/x/sync/errgroup"
|
||
)
|
||
|
||
type Router struct {
|
||
r *gin.Engine
|
||
addr string
|
||
log *logger.Logger
|
||
}
|
||
|
||
type AddRouter interface {
|
||
AddRoute(*gin.Engine)
|
||
}
|
||
|
||
func NewRouter(addr string, log *logger.Logger, rate settings.RateLimitConfig, routes ...AddRouter) *Router {
|
||
r := gin.New()
|
||
|
||
r.Use(cors.New(cors.Config{
|
||
AllowOrigins: []string{"*"},
|
||
AllowMethods: []string{"GET", "POST"},
|
||
AllowHeaders: []string{"Origin", "Content-Type"},
|
||
ExposeHeaders: []string{"Content-Length"},
|
||
AllowCredentials: true,
|
||
MaxAge: 12 * time.Hour,
|
||
}))
|
||
|
||
r.Use(GinLogger(log), GinRecovery(log, true), GinLog(log), ErrWapper(GinRateLimit(rate)))
|
||
|
||
for _, route := range routes {
|
||
route.AddRoute(r)
|
||
}
|
||
|
||
pprof.Register(r)
|
||
|
||
return &Router{
|
||
r: r,
|
||
addr: addr,
|
||
log: log,
|
||
}
|
||
}
|
||
|
||
func (r *Router) Run(ctx context.Context) error {
|
||
srv := &http.Server{
|
||
Addr: r.addr,
|
||
Handler: r.r,
|
||
}
|
||
|
||
r.log.Sugar().Infof("Server listen on %s", r.addr)
|
||
|
||
wg, ctx := errgroup.WithContext(ctx)
|
||
wg.Go(func() error {
|
||
// 开启一个goroutine启动服务
|
||
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||
r.log.Error("listen: %s\n", zap.Error(err))
|
||
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
})
|
||
|
||
wg.Go(func() error {
|
||
// 等待中断信号来优雅地关闭服务器,为关闭服务器操作设置一个5秒的超时
|
||
quit := make(chan os.Signal, 1) // 创建一个接收信号的通道
|
||
// kill 默认会发送 syscall.SIGTERM 信号
|
||
// kill -2 发送 syscall.SIGINT 信号,我们常用的Ctrl+C就是触发系统SIGINT信号
|
||
// kill -9 发送 syscall.SIGKILL 信号,但是不能被捕获,所以不需要添加它
|
||
// signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
|
||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞
|
||
select {
|
||
case <-ctx.Done():
|
||
r.log.Error("Http Server Cancel by ctx")
|
||
case <-quit:
|
||
}
|
||
// 阻塞在此,当接收到上述两种信号时才会往下执行
|
||
r.log.Info("Shutdown Server ...")
|
||
// 创建一个5秒超时的context
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
defer cancel()
|
||
// 5秒内优雅关闭服务(将未处理完的请求处理完再关闭服务),超过5秒就超时退出
|
||
if err := srv.Shutdown(ctx); err != nil {
|
||
r.log.Error("Server Shutdown: ", zap.Error(err))
|
||
|
||
return err
|
||
}
|
||
|
||
r.log.Info("Server exiting")
|
||
|
||
return errors.New("Server Shutdown")
|
||
})
|
||
|
||
if err := wg.Wait(); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
/*
|
||
func Setup(log *logger.Logger, rate settings.RateLimitConfig, jwtC settings.JwtConfig) *gin.Engine {
|
||
cjwt := jwt.New(jwt.WithSalt(jwtC.Salt), jwt.WithExpire(time.Duration(jwtC.Expire)*time.Second))
|
||
|
||
r := gin.New()
|
||
|
||
r.Use(cors.New(cors.Config{
|
||
AllowOrigins: []string{"*"},
|
||
AllowMethods: []string{"GET", "POST"},
|
||
AllowHeaders: []string{"Origin", "Content-Type"},
|
||
ExposeHeaders: []string{"Content-Length"},
|
||
AllowCredentials: true,
|
||
MaxAge: 12 * time.Hour,
|
||
}))
|
||
|
||
r.Use(GinLogger(log), GinRecovery(log, true), GinLog(log), errWapper(GinRateLimit(rate)))
|
||
|
||
// 静态文件服务
|
||
r.Static("/static", "./static")
|
||
r.StaticFile("/", "./static/index.html")
|
||
|
||
r.GET("login", controller.LoginPage)
|
||
|
||
r.POST("/api/login", errWapper(controller.UserSignInHandler(cjwt)))
|
||
r.POST("/api/logout", controller.UserLogOutHandler)
|
||
|
||
g1 := r.Group("/api")
|
||
g1.Use(errWapper(GinJwtAuthor(cjwt)))
|
||
{
|
||
g1.GET("/system-info", errWapper(controller.SystemInfoHandle))
|
||
g1.POST("/upload", errWapper(controller.FileUploadHandle))
|
||
g1.GET("/files", errWapper(controller.FileListHandle))
|
||
g1.GET("/download", errWapper(controller.FileDownloadHandle))
|
||
}
|
||
|
||
r.GET("/ws/terminal", errWapper(GinJwtAuthor(cjwt)), errWapper(controller.TerminalHandle()))
|
||
|
||
// unisr := r.Group("/api/unis")
|
||
// unisr.Use(errWapper(GinCheckServerId), errWapper(GinStoreRequest))
|
||
// {
|
||
// unisr.POST("/config/v1/add", errWapper(unis.StationConfig))
|
||
// }
|
||
|
||
return r
|
||
}
|
||
*/
|