Files
platform/web/web.go

167 lines
3.6 KiB
Go
Raw Normal View History

2025-03-15 16:07:45 +08:00
package web
import (
"github.com/gofiber/fiber/v2"
2025-03-18 17:57:07 +08:00
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
2025-03-18 17:57:07 +08:00
"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"
g "platform/web/globals"
q "platform/web/queries"
"runtime"
"strings"
"time"
)
2025-03-15 16:07:45 +08:00
// region web
2025-03-15 16:07:45 +08:00
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.Init()
q.SetDefault(g.DB)
// config
2025-03-18 17:57:07 +08:00
s.fiber = fiber.New(fiber.Config{
ProxyHeader: fiber.HeaderXForwardedFor,
2025-03-18 17:57:07 +08:00
ErrorHandler: ErrorHandler,
})
// middlewares
s.fiber.Use(newRecover())
s.fiber.Use(newRequestId())
s.fiber.Use(newLogger())
2025-03-18 17:57:07 +08:00
// routes
2025-03-18 17:57:07 +08:00
ApplyRouters(s.fiber)
2025-03-15 16:07:45 +08:00
2025-04-01 10:51:32 +08:00
// pprof
go func() {
2025-04-01 10:51:32 +08:00
runtime.SetBlockProfileRate(1)
err := http.ListenAndServe(":6060", nil)
if err != nil {
slog.Error("pprof 服务错误", slog.Any("err", err))
}
}()
// listen
slog.Info("服务开始监听 :8080")
err := s.fiber.Listen("0.0.0.0:8080")
2025-03-15 16:07:45 +08:00
if err != nil {
2025-03-18 17:57:07 +08:00
slog.Error("Failed to start server", slog.Any("err", err))
2025-03-15 16:07:45 +08:00
}
slog.Info("服务已停止")
2025-03-15 16:07:45 +08:00
return nil
}
func (s *Server) Stop() {
err := g.ExitRedis()
if err != nil {
slog.Error("Failed to close Redis connection", slog.Any("err", err))
}
err = g.ExitOrm()
if err != nil {
slog.Error("Failed to close database connection", slog.Any("err", err))
}
err = s.fiber.Shutdown()
2025-03-15 16:07:45 +08:00
if err != nil {
2025-03-18 17:57:07 +08:00
slog.Error("Failed to shutdown server", slog.Any("err", err))
2025-03-15 16:07:45 +08:00
}
}
// endregion
// region middlewares
func newRequestId() fiber.Handler {
return requestid.New(requestid.Config{
Generator: func() string {
binary, _ := uuid.New().MarshalBinary()
return base62.EncodeToString(binary)
},
})
}
func newLogger() 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",
2025-05-09 15:06:22 +08:00
Next: func(c *fiber.Ctx) bool {
authCtx, ok := c.Locals("auth").(*auth.Context)
if ok {
c.Locals("authtype", authCtx.Payload.Type.ToStr())
c.Locals("authid", authCtx.Payload.Id)
} else {
c.Locals("authtype", auth.PayloadNone.ToStr())
c.Locals("authid", 0)
}
2025-05-09 15:06:22 +08:00
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 latency = strings.TrimSpace(logVars[4])
var errStr = strings.TrimSpace(logVars[5])
slog.Info("接口请求",
slog.String("identity", c.Locals("authtype").(string)),
slog.Int("visitor", c.Locals("authid").(int)),
slog.String("ip", c.IP()),
slog.String("ua", c.Get("User-Agent")),
slog.String("method", c.Method()),
slog.String("path", c.Path()),
slog.Int("status", c.Response().StatusCode()),
slog.String("error", errStr),
slog.String("latency", latency),
slog.Time("time", reqTime),
)
},
})
}
func newRecover() fiber.Handler {
2025-06-24 11:36:27 +08:00
return recover.New(recover.Config{
EnableStackTrace: true,
})
}
// endregion