package web import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/requestid" "github.com/google/uuid" "github.com/jxskiss/base62" "log/slog" "net/http" _ "net/http/pprof" "platform/web/auth" "platform/web/core" g "platform/web/globals" m "platform/web/models" q "platform/web/queries" "runtime" "strconv" "strings" "time" ) // region web type Config struct { Listen string } type Server struct { config *Config fiber *fiber.App } func New(config *Config) (*Server, error) { _config := config if config == nil { _config = &Config{} } return &Server{ config: _config, }, nil } func (s *Server) Run() error { // inits g.InitBaiyin() g.InitAlipay() g.InitWechatPay() g.InitAliyun() g.InitValidator() // config s.fiber = fiber.New(fiber.Config{ ProxyHeader: fiber.HeaderXForwardedFor, ErrorHandler: ErrorHandler, }) // middlewares s.fiber.Use(useRequestId()) s.fiber.Use(useLogger()) // routes ApplyRouters(s.fiber) // pprof go func() { runtime.SetBlockProfileRate(1) err := http.ListenAndServe(":6060", nil) if err != nil { slog.Error("pprof 服务错误", slog.Any("err", err)) } }() // listen slog.Info("Server started on :8080") err := s.fiber.Listen(":8080") if err != nil { slog.Error("Failed to start server", slog.Any("err", err)) } slog.Info("Server stopped") return nil } func (s *Server) Stop() { err := s.fiber.Shutdown() if err != nil { slog.Error("Failed to shutdown server", slog.Any("err", err)) } } // endregion // region requestid func useRequestId() fiber.Handler { return requestid.New(requestid.Config{ Generator: func() string { binary, _ := uuid.New().MarshalBinary() return base62.EncodeToString(binary) }, }) } // endregion // region logger func useLogger() fiber.Handler { return logger.New(logger.Config{ DisableColors: true, Format: "🚀 ${time} | ${locals:authtype} ${locals:authid} | ${method} ${path} | ${status} | ${latency} | ${error}\n", TimeFormat: "2006-01-02 15:04:05", TimeZone: "Asia/Shanghai", Next: func(c *fiber.Ctx) bool { c.Locals("authtype", auth.PayloadNone.ToStr()) c.Locals("authid", 0) return false }, Done: func(c *fiber.Ctx, logBytes []byte) { var logStr = strings.TrimPrefix(string(logBytes), "🚀") var logVars = strings.Split(logStr, "|") var reqTimeStr = strings.TrimSpace(logVars[0]) reqTime, err := time.ParseInLocation("2006-01-02 15:04:05", reqTimeStr, time.Local) if err != nil { slog.Error("时间解析错误", slog.Any("err", err)) return } var authInfo = strings.Split(strings.TrimSpace(logVars[1]), " ") var authType = auth.PayloadTypeFromStr(strings.TrimSpace(authInfo[0])) authID, err := strconv.Atoi(strings.TrimSpace(authInfo[1])) if err != nil { slog.Error("负载ID解析错误", slog.Any("err", err)) return } var latency = strings.TrimSpace(logVars[4]) var errStr = strings.TrimSpace(logVars[5]) var item = &m.LogsRequest{ IP: c.IP(), Ua: c.Get("User-Agent"), Method: c.Method(), Path: c.Path(), Latency: latency, Status: int32(c.Response().StatusCode()), Error: errStr, Time: core.LocalDateTime(reqTime), } if authType != auth.PayloadNone { item.Identity = int32(authType) } if authID != 0 { item.Visitor = int32(authID) } err = q.LogsRequest.Create(item) if err != nil { slog.Error("日志记录错误", slog.Any("err", err)) return } }, }) } // endregion