package main import ( _ "FileRelay/docs" "FileRelay/internal/api/admin" "FileRelay/internal/api/middleware" "FileRelay/internal/api/public" "FileRelay/internal/bootstrap" "FileRelay/internal/config" "FileRelay/internal/task" "context" "fmt" "log" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" ) // @title 文件暂存柜 API // @version 1.0 // @description 自托管的文件暂存柜后端系统 API 文档 // @termsOfService http://swagger.io/terms/ // @contact.name API Support // @contact.url http://www.swagger.io/support // @contact.email support@swagger.io // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @BasePath / // @securityDefinitions.apikey AdminAuth // @in header // @name Authorization // @description Type "Bearer " to authenticate. func main() { // 1. 加载配置 if err := config.LoadConfig("config/config.yaml"); err != nil { log.Fatalf("Failed to load config: %v", err) } // 2. 初始化 bootstrap.InitDB() // 3. 启动清理任务 cleaner := task.NewCleaner() go cleaner.Start(context.Background()) // 4. 设置路由 r := gin.Default() // 配置更完善的 CORS corsConfig := cors.DefaultConfig() corsConfig.AllowAllOrigins = true corsConfig.AllowHeaders = append(corsConfig.AllowHeaders, "Authorization", "Accept", "X-Requested-With") corsConfig.AllowMethods = append(corsConfig.AllowMethods, "OPTIONS") r.Use(cors.New(corsConfig)) // Swagger 文档 r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) // 公共接口 uploadHandler := public.NewUploadHandler() pickupHandler := public.NewPickupHandler() publicConfigHandler := public.NewConfigHandler() api := r.Group("/api") { api.GET("/config", publicConfigHandler.GetPublicConfig) // 统一使用 /batches 作为资源路径 api.POST("/batches", uploadHandler.Upload) api.POST("/batches/text", uploadHandler.UploadText) api.GET("/batches/:pickup_code", middleware.PickupRateLimit(), pickupHandler.Pickup) api.GET("/batches/:pickup_code/download", pickupHandler.DownloadBatch) // 文件下载保持 /files/:id/download 风格 api.GET("/files/:file_id/download", pickupHandler.DownloadFile) // 保持旧路由兼容性 (可选,但为了平滑过渡通常建议保留一段时间或直接更新) // 这里根据需求“调整不符合规范的”,我将直接采用新路由 } // 管理员接口 authHandler := admin.NewAuthHandler() batchHandler := admin.NewBatchHandler() tokenHandler := admin.NewTokenHandler() configHandler := admin.NewConfigHandler() r.POST("/admin/login", authHandler.Login) adm := r.Group("/admin") adm.Use(middleware.AdminAuth()) { adm.GET("/config", configHandler.GetConfig) adm.PUT("/config", configHandler.UpdateConfig) adm.GET("/batches", batchHandler.ListBatches) adm.GET("/batches/:batch_id", batchHandler.GetBatch) adm.PUT("/batches/:batch_id", batchHandler.UpdateBatch) adm.DELETE("/batches/:batch_id", batchHandler.DeleteBatch) adm.GET("/api-tokens", tokenHandler.ListTokens) adm.POST("/api-tokens", tokenHandler.CreateToken) adm.DELETE("/api-tokens/:id", tokenHandler.DeleteToken) adm.POST("/api-tokens/:id/revoke", tokenHandler.RevokeToken) } // 5. 运行 port := 8080 fmt.Printf("Server is running on port %d\n", port) r.Run(fmt.Sprintf(":%d", port)) }