server.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package bootstrap
  2. import (
  3. "net/http"
  4. "path/filepath"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/gin-contrib/cors"
  9. "github.com/gin-gonic/gin"
  10. routers "dbview/service/internal/modules"
  11. "go.uber.org/zap"
  12. )
  13. // Server HTTP服务器
  14. type Server struct {
  15. app *App
  16. engine *gin.Engine
  17. }
  18. // NewServer 创建新的服务器实例
  19. func NewServer(app *App) *Server {
  20. return &Server{
  21. app: app,
  22. }
  23. }
  24. // Setup 设置服务器
  25. func (s *Server) Setup() {
  26. // 创建Gin引擎
  27. s.engine = gin.Default()
  28. // 设置中间件(已优化重复CORS)
  29. s.setupMiddleware()
  30. // 1. 先注册所有API路由(确保API路由优先)
  31. s.registerRoutes()
  32. // 2. 挂载本地静态文件(Vue打包的dist目录)
  33. //s.mountStaticFiles()
  34. s.app.Logger.Info("HTTP服务器设置完成",
  35. zap.String("addr", s.app.Config.Server.Ip),
  36. zap.Bool("cors_enabled", true),
  37. zap.Bool("audit_enabled", s.app.Config.Audit.Enabled))
  38. }
  39. // 新增:挂载本地静态文件(不使用embed)
  40. func (s *Server) mountStaticFiles() {
  41. // 获取本地dist目录的绝对路径(确保程序能找到Vue打包后的文件)
  42. // 注意:dist目录需放在项目根目录(与main.go同级)
  43. distPath, err := filepath.Abs("dist")
  44. if err != nil {
  45. s.app.Logger.Error("获取静态文件目录失败", zap.Error(err))
  46. return
  47. }
  48. // 挂载静态文件到 /static 前缀(与API路由完全隔离,避免冲突)
  49. // 访问路径:/static/index.html → 对应本地 dist/index.html
  50. s.engine.StaticFS("/static", http.Dir(distPath))
  51. s.app.Logger.Info("静态文件挂载成功", zap.String("dist_path", distPath), zap.String("mount_path", "/static"))
  52. // 3. 处理Vue SPA前端路由(如 /dashboard、/settings 等前端路由)
  53. s.engine.NoRoute(func(c *gin.Context) {
  54. // 过滤API路由(避免API请求被误处理为前端路由)
  55. // 现有API前缀:/connection_storage、/db_connection、/db_view、/sql_execute、/api 等
  56. apiPrefixes := []string{
  57. "/connection_storage",
  58. "/db_connection",
  59. "/db_view",
  60. "/sql_execute",
  61. "/api",
  62. }
  63. for _, prefix := range apiPrefixes {
  64. if strings.HasPrefix(c.Request.URL.Path, prefix) {
  65. c.Status(http.StatusNotFound) // API路由不存在时返回404
  66. return
  67. }
  68. }
  69. // 非API路由:返回dist目录下的index.html(由前端路由处理)
  70. indexPath := filepath.Join(distPath, "index.html")
  71. c.File(indexPath)
  72. })
  73. }
  74. // setupMiddleware 设置中间件(清理重复CORS)
  75. func (s *Server) setupMiddleware() {
  76. // 依赖注入中间件 - 暂时注释,等待 middleware 包实现
  77. // s.engine.Use(middleware.InjectDependencies(s.app.StorageManager, s.app.ConnectionPool))
  78. // 自定义CORS配置(保留自定义配置,移除重复的cors.Default())
  79. s.engine.Use(cors.New(cors.Config{
  80. AllowOrigins: []string{"*"}, // 允许所有来源
  81. AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, // 允许的方法
  82. AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"}, // 允许的头部
  83. ExposeHeaders: []string{"Content-Length"}, // 可暴露的头部
  84. AllowCredentials: true, // 允许携带凭据
  85. MaxAge: 12 * time.Hour, // 缓存时间
  86. }))
  87. // 客户端地址中间件 - 暂时注释,等待 middleware 包实现
  88. // s.engine.Use(middleware.ClientAddrMiddleware())
  89. // Gin恢复中间件(异常恢复)
  90. s.engine.Use(gin.Recovery())
  91. // 使用修复后的日志中间件 - 暂时注释,等待 middleware 包实现
  92. // s.engine.Use(middleware.RequestLoggerMiddleware())
  93. }
  94. // registerRoutes 注册路由(现有逻辑不变)
  95. func (s *Server) registerRoutes() {
  96. // 注册模块路由
  97. routers.RegisterRoutes(s.engine, s.app.StorageManager, s.app.TaskManager, s.app.ConnectionPool)
  98. // 基础健康检查路由
  99. s.engine.GET("/health", func(c *gin.Context) {
  100. c.JSON(200, gin.H{
  101. "status": "ok",
  102. "time": time.Now().Format(time.RFC3339),
  103. })
  104. })
  105. s.app.Logger.Info("路由注册完成")
  106. }
  107. // Start 启动服务器(现有逻辑不变)
  108. func (s *Server) Start() error {
  109. s.app.Logger.Info("HTTP服务器启动完成", zap.String("IP:Port", s.app.Config.Server.Ip+":"+strconv.Itoa(s.app.Config.Server.Port)))
  110. addr := s.app.Config.Server.Ip + ":" + strconv.Itoa(s.app.Config.Server.Port)
  111. return s.engine.Run(addr)
  112. }