90 lines
3.3 KiB
Go
90 lines
3.3 KiB
Go
package router
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/gin-contrib/cors"
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"sproutworkcollect-backend/internal/config"
|
|
"sproutworkcollect-backend/internal/handler"
|
|
"sproutworkcollect-backend/internal/middleware"
|
|
"sproutworkcollect-backend/internal/service"
|
|
)
|
|
|
|
// Setup creates and configures the Gin engine: middleware, services, handlers, and routes.
|
|
func Setup(cfg *config.Config) *gin.Engine {
|
|
if !cfg.Debug {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
}
|
|
|
|
r := gin.Default()
|
|
|
|
// Allow files up to 32 MB to stay in memory; larger ones spill to temp disk files.
|
|
// This keeps RAM usage bounded even for gigabyte-scale uploads.
|
|
r.MaxMultipartMemory = 32 << 20
|
|
|
|
// 允许所有来源,并显式放开 Authorization 头,解决跨域访问后台接口时的预检失败问题。
|
|
corsCfg := cors.Config{
|
|
AllowOrigins: []string{"*"},
|
|
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
|
AllowHeaders: []string{
|
|
"Origin",
|
|
"Content-Type",
|
|
"Accept",
|
|
"Authorization",
|
|
"X-Requested-With",
|
|
},
|
|
ExposeHeaders: []string{"Content-Length"},
|
|
AllowCredentials: false,
|
|
MaxAge: 12 * time.Hour,
|
|
}
|
|
r.Use(cors.New(corsCfg))
|
|
|
|
// ─── Services ─────────────────────────────────────────────────────────────
|
|
workSvc := service.NewWorkService(cfg)
|
|
settingsSvc := service.NewSettingsService(cfg)
|
|
rateLimiter := service.NewRateLimiter()
|
|
|
|
// ─── Handlers ─────────────────────────────────────────────────────────────
|
|
pub := handler.NewPublicHandler(workSvc, settingsSvc, rateLimiter)
|
|
media := handler.NewMediaHandler(workSvc, rateLimiter)
|
|
admin := handler.NewAdminHandler(workSvc)
|
|
|
|
// ─── Public routes ────────────────────────────────────────────────────────
|
|
r.GET("/", func(c *gin.Context) {
|
|
c.JSON(200, gin.H{
|
|
"service": "SproutWorkCollect API",
|
|
"version": "v1",
|
|
"endpoints": []string{"/api/settings", "/api/works", "/api/works/{work_id}", "/api/search", "/api/categories", "/api/like/{work_id}"},
|
|
})
|
|
})
|
|
|
|
api := r.Group("/api")
|
|
{
|
|
api.GET("/settings", pub.GetSettings)
|
|
api.GET("/works", pub.GetWorks)
|
|
api.GET("/works/:work_id", pub.GetWorkDetail)
|
|
api.GET("/search", pub.SearchWorks)
|
|
api.GET("/categories", pub.GetCategories)
|
|
api.POST("/like/:work_id", pub.LikeWork)
|
|
|
|
api.GET("/image/:work_id/:filename", media.ServeImage)
|
|
api.GET("/video/:work_id/:filename", media.ServeVideo)
|
|
api.GET("/download/:work_id/:platform/:filename", media.DownloadFile)
|
|
}
|
|
|
|
// ─── Admin routes (token-protected) ──────────────────────────────────────
|
|
adm := api.Group("/admin", middleware.AdminAuth(cfg.AdminToken))
|
|
{
|
|
adm.GET("/works", admin.GetWorks)
|
|
adm.POST("/works", admin.CreateWork)
|
|
adm.PUT("/works/:work_id", admin.UpdateWork)
|
|
adm.DELETE("/works/:work_id", admin.DeleteWork)
|
|
adm.POST("/upload/:work_id/:file_type", admin.UploadFile)
|
|
adm.DELETE("/delete-file/:work_id/:file_type/:filename", admin.DeleteFile)
|
|
}
|
|
|
|
return r
|
|
}
|