package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "u-desk/internal/agent/config" agentmw "u-desk/internal/agent/middleware" "u-desk/internal/agent/handler" "u-desk/internal/filesystem" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) func main() { cfg, err := config.Load("configs/agent.yaml") if err != nil { log.Fatalf("[FATAL] 加载配置失败: %v", err) } fsConfig := filesystem.DefaultConfig() fsSvc, err := filesystem.NewFileSystemService(fsConfig) if err != nil { log.Fatalf("[FATAL] 初始化文件服务失败: %v", err) } e := echo.New() e.HideBanner = true e.HidePort = true e.Use(middleware.Recover()) e.Use(middleware.Logger()) e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: cfg.CORS.AllowedOrigins, AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE, echo.PATCH, echo.OPTIONS}, AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAuthorization, echo.HeaderAccept}, })) if cfg.Auth.Token != "" { e.Use(agentmw.Auth(cfg.Auth.Token)) } h := handler.New(fsSvc, cfg) api := e.Group("/api/v1") { api.GET("/ping", h.Ping) api.GET("/info", h.Info) // 文件操作 — 所有通过 ?path= 参数传递路径 api.GET("/fs", h.ListOrStat) // ?path=xxx [&action=stat] api.GET("/fs/read", h.ReadFile) // ?path=xxx api.PUT("/fs/write", h.WriteFile) // ?path=xxx & body={content} api.POST("/fs/create", h.Create) // ?path=xxx & body={type,name} api.DELETE("/fs/delete", h.Delete) // ?path=xxx api.PATCH("/fs/rename", h.Rename) // ?path=xxx & body={new_path} api.POST("/fs/upload", h.Upload) // ?path=xxx & body={content} api.GET("/fs/detect", h.DetectType) // ?path=xxx sys := api.Group("/system") { sys.GET("/common-paths", h.CommonPaths) sys.GET("/drives", h.Drives) sys.GET("/stats", h.Stats) } proxy := api.Group("/proxy") { proxy.GET("/localfs/*", h.FileServerProxy) proxy.GET("/html-preview", h.HTMLPreviewProxy) } } addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port) go func() { log.Printf("[INFO] u-fs-agent 启动于 %s", addr) if err := e.Start(addr); err != nil && err != http.ErrServerClosed { log.Fatalf("[FATAL] HTTP 服务器错误: %v", err) } }() go func() { if _, err := filesystem.StartLocalFileServer(); err != nil { log.Printf("[WARN] 文件服务器启动失败(媒体预览不可用): %v", err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("[INFO] 正在关闭...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() filesystem.ShutdownLocalFileServer() e.Shutdown(ctx) fsSvc.Close(ctx) log.Println("[INFO] 已关闭") }