Files
go-123pan-pic/internal/handler/router.go
RainySY 7229dfa1b7 refactor: decouple services from global config and clean up structure
- Remove duplicate UploadBaseURL constant (identical to APIBaseURL)
- Pass parentFileID and customDomain into service constructors instead of
  reading from config.GlobalConfig at call time, eliminating hidden global
  state dependencies in the service layer
- Replace []interface{} response building in HandleList with a typed
  imageResponse struct for compile-time safety
- Extract inline CORS closure from main.go into handler.CORSMiddleware(),
  consistent with how AuthMiddleware is organized
- Remove narrating comments throughout; keep only the non-obvious one
  explaining why DoRawPUT omits auth headers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 14:48:11 +08:00

79 lines
1.9 KiB
Go

package handler
import (
"crypto/subtle"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"imagehost/internal/config"
"imagehost/static"
)
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
return
}
c.Next()
}
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenCfg := config.GlobalConfig.APIToken
if tokenCfg == "" {
c.Next()
return
}
authHeader := c.GetHeader("Authorization")
queryToken := c.Query("token")
var clientToken string
if strings.HasPrefix(authHeader, "Bearer ") {
clientToken = strings.TrimPrefix(authHeader, "Bearer ")
} else if authHeader != "" {
clientToken = authHeader
} else {
clientToken = queryToken
}
// constant-time compare prevents timing-based token enumeration
if subtle.ConstantTimeCompare([]byte(clientToken), []byte(tokenCfg)) != 1 {
c.JSON(http.StatusForbidden, gin.H{
"code": 403,
"message": "未经授权访问:请提供正确的 api_token 以进行操作。",
})
c.Abort()
return
}
c.Next()
}
}
func ConfigureRoutes(r *gin.Engine, imgHandler *ImageHandler, upHandler *UploadHandler) {
api := r.Group("/api")
api.Use(AuthMiddleware())
{
api.POST("/upload", upHandler.HandleUpload)
api.GET("/images", imgHandler.HandleList)
api.DELETE("/images/:id", imgHandler.HandleDelete)
}
r.StaticFS("/static", http.FS(static.FS))
r.GET("/", func(c *gin.Context) {
htmlData, err := static.FS.ReadFile("index.html")
if err != nil {
c.String(http.StatusInternalServerError, "内置静态首页打包遗失")
return
}
c.Data(http.StatusOK, "text/html; charset=utf-8", htmlData)
})
}