123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package bootstrap
- import (
- "context"
- "designs/app/common/request"
- "designs/app/common/response"
- "designs/config"
- "designs/global"
- "designs/route"
- "fmt"
- "go.uber.org/zap"
- "log"
- "net/http"
- "os"
- "os/signal"
- "runtime/debug"
- "syscall"
- "time"
- "github.com/gin-gonic/gin"
- )
- // 回收致命错误
- func CustomRecovery(c *gin.Context) {
- defer func() {
- if r := recover(); r != nil {
- if v, ok := r.(request.ValidateError); ok {
- response.ParameterError(c, v)
- return
- }
- //打印错误堆栈信息
- errTitle := fmt.Sprintf("panic: %v", r)
- errMsg := fmt.Sprintf("stack: %v", string(debug.Stack()))
- global.App.Log.Error("custom_recovery", zap.Any("info", errTitle), zap.Stack("stack"))
- response.ServerError(c, errTitle+errMsg)
- }
- }()
- //继续后续接口调用
- c.Next()
- }
- func corsMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- c.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 或者指定允许的源
- c.Writer.Header().Set("Access-Control-Max-Age", "86400") // 缓存请求信息
- c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
- c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Length, Content-Type, Authorization, X-Requested-With")
- c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Type")
- c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
- if c.Request.Method == "OPTIONS" {
- c.AbortWithStatus(204)
- return
- }
- c.Next()
- }
- }
- func setupRouter() *gin.Engine {
- if config.Get("app.env") == "production" {
- gin.SetMode(gin.ReleaseMode)
- }
- router := gin.New()
- router.Use(gin.Logger(), CustomRecovery)
- router.Use(corsMiddleware())
- // 跨域处理
- //router.Use(middleware.Cors())
- // 前端项目静态资源
- // router.StaticFile("/", "./static/dist/index.html")
- // router.Static("/assets", "./static/dist/assets")
- // router.StaticFile("/favicon.ico", "./static/dist/favicon.ico")
- // 其他静态资源
- // router.Static("/public", "./static")
- // router.Static("/storage", "./storage/app/public")
- // 注册 api 分组路由
- apiGroup := router.Group("")
- route.SetApiGroupRoutes(apiGroup)
- return router
- }
- func RunServer() {
- r := setupRouter()
- srv := &http.Server{
- Addr: ":" + config.Get("app.port"),
- ReadTimeout: 60 * time.Second,
- WriteTimeout: 60 * time.Second,
- Handler: r,
- }
- fmt.Println("Starting server at port " + config.Get("app.port") + " ...")
- go func() {
- if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- log.Fatalf("listen: %s\n", err)
- }
- }()
- // 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)
- quit := make(chan os.Signal)
- signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
- <-quit
- log.Println("Shutdown Server ...")
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- if err := srv.Shutdown(ctx); err != nil {
- log.Fatal("Server Shutdown:", err)
- }
- log.Println("Server exiting")
- }
|