| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- package bootstrap
- import (
- "net/http"
- "path/filepath"
- "strconv"
- "strings"
- "time"
- "github.com/gin-contrib/cors"
- "github.com/gin-gonic/gin"
- routers "dbview/service/internal/modules"
- "go.uber.org/zap"
- )
- // Server HTTP服务器
- type Server struct {
- app *App
- engine *gin.Engine
- }
- // NewServer 创建新的服务器实例
- func NewServer(app *App) *Server {
- return &Server{
- app: app,
- }
- }
- // Setup 设置服务器
- func (s *Server) Setup() {
- // 创建Gin引擎
- s.engine = gin.Default()
- // 设置中间件(已优化重复CORS)
- s.setupMiddleware()
- // 1. 先注册所有API路由(确保API路由优先)
- s.registerRoutes()
- // 2. 挂载本地静态文件(Vue打包的dist目录)
- //s.mountStaticFiles()
- s.app.Logger.Info("HTTP服务器设置完成",
- zap.String("addr", s.app.Config.Server.Ip),
- zap.Bool("cors_enabled", true),
- zap.Bool("audit_enabled", s.app.Config.Audit.Enabled))
- }
- // 新增:挂载本地静态文件(不使用embed)
- func (s *Server) mountStaticFiles() {
- // 获取本地dist目录的绝对路径(确保程序能找到Vue打包后的文件)
- // 注意:dist目录需放在项目根目录(与main.go同级)
- distPath, err := filepath.Abs("dist")
- if err != nil {
- s.app.Logger.Error("获取静态文件目录失败", zap.Error(err))
- return
- }
- // 挂载静态文件到 /static 前缀(与API路由完全隔离,避免冲突)
- // 访问路径:/static/index.html → 对应本地 dist/index.html
- s.engine.StaticFS("/static", http.Dir(distPath))
- s.app.Logger.Info("静态文件挂载成功", zap.String("dist_path", distPath), zap.String("mount_path", "/static"))
- // 3. 处理Vue SPA前端路由(如 /dashboard、/settings 等前端路由)
- s.engine.NoRoute(func(c *gin.Context) {
- // 过滤API路由(避免API请求被误处理为前端路由)
- // 现有API前缀:/connection_storage、/db_connection、/db_view、/sql_execute、/api 等
- apiPrefixes := []string{
- "/connection_storage",
- "/db_connection",
- "/db_view",
- "/sql_execute",
- "/api",
- }
- for _, prefix := range apiPrefixes {
- if strings.HasPrefix(c.Request.URL.Path, prefix) {
- c.Status(http.StatusNotFound) // API路由不存在时返回404
- return
- }
- }
- // 非API路由:返回dist目录下的index.html(由前端路由处理)
- indexPath := filepath.Join(distPath, "index.html")
- c.File(indexPath)
- })
- }
- // setupMiddleware 设置中间件(清理重复CORS)
- func (s *Server) setupMiddleware() {
- // 依赖注入中间件 - 暂时注释,等待 middleware 包实现
- // s.engine.Use(middleware.InjectDependencies(s.app.StorageManager, s.app.ConnectionPool))
- // 自定义CORS配置(保留自定义配置,移除重复的cors.Default())
- s.engine.Use(cors.New(cors.Config{
- AllowOrigins: []string{"*"}, // 允许所有来源
- AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, // 允许的方法
- AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"}, // 允许的头部
- ExposeHeaders: []string{"Content-Length"}, // 可暴露的头部
- AllowCredentials: true, // 允许携带凭据
- MaxAge: 12 * time.Hour, // 缓存时间
- }))
- // 客户端地址中间件 - 暂时注释,等待 middleware 包实现
- // s.engine.Use(middleware.ClientAddrMiddleware())
- // Gin恢复中间件(异常恢复)
- s.engine.Use(gin.Recovery())
- // 使用修复后的日志中间件 - 暂时注释,等待 middleware 包实现
- // s.engine.Use(middleware.RequestLoggerMiddleware())
- }
- // registerRoutes 注册路由(现有逻辑不变)
- func (s *Server) registerRoutes() {
- // 注册模块路由
- routers.RegisterRoutes(s.engine, s.app.StorageManager, s.app.TaskManager, s.app.ConnectionPool)
- // 基础健康检查路由
- s.engine.GET("/health", func(c *gin.Context) {
- c.JSON(200, gin.H{
- "status": "ok",
- "time": time.Now().Format(time.RFC3339),
- })
- })
- s.app.Logger.Info("路由注册完成")
- }
- // Start 启动服务器(现有逻辑不变)
- func (s *Server) Start() error {
- s.app.Logger.Info("HTTP服务器启动完成", zap.String("IP:Port", s.app.Config.Server.Ip+":"+strconv.Itoa(s.app.Config.Server.Port)))
- addr := s.app.Config.Server.Ip + ":" + strconv.Itoa(s.app.Config.Server.Port)
- return s.engine.Run(addr)
- }
|