kra/internal/server/middleware/gin_cors.go

87 lines
2.1 KiB
Go

package middleware
import (
"net/http"
"github.com/gin-gonic/gin"
)
// GinCORSWhitelist Gin CORS白名单配置
type GinCORSWhitelist struct {
AllowOrigin string
AllowHeaders string
AllowMethods string
ExposeHeaders string
AllowCredentials bool
}
// GinCORSConfig Gin CORS配置
type GinCORSConfig struct {
// Mode 模式: allow-all, whitelist, strict-whitelist
Mode string
Whitelist []GinCORSWhitelist
}
// 全局CORS配置
var ginCorsConfig *GinCORSConfig
// SetGinCORSConfig 设置Gin CORS配置
func SetGinCORSConfig(cfg *GinCORSConfig) {
ginCorsConfig = cfg
}
// CorsByRules 按照配置处理跨域请求(与 kra 保持一致)
func CorsByRules() gin.HandlerFunc {
// 放行全部
if ginCorsConfig == nil || ginCorsConfig.Mode == "allow-all" {
return Cors()
}
return func(c *gin.Context) {
origin := c.GetHeader("origin")
whitelist := checkGinCors(origin)
// 通过检查, 添加请求头
if whitelist != nil {
c.Header("Access-Control-Allow-Origin", whitelist.AllowOrigin)
c.Header("Access-Control-Allow-Headers", whitelist.AllowHeaders)
c.Header("Access-Control-Allow-Methods", whitelist.AllowMethods)
c.Header("Access-Control-Expose-Headers", whitelist.ExposeHeaders)
if whitelist.AllowCredentials {
c.Header("Access-Control-Allow-Credentials", "true")
}
}
// 严格白名单模式且未通过检查,直接拒绝处理请求
if whitelist == nil && ginCorsConfig.Mode == "strict-whitelist" {
// 健康检查放行
if !(c.Request.Method == "GET" && c.Request.URL.Path == "/health") {
c.AbortWithStatus(http.StatusForbidden)
return
}
} else {
// 非严格白名单模式,无论是否通过检查均放行所有 OPTIONS 方法
if c.Request.Method == http.MethodOptions {
c.AbortWithStatus(http.StatusNoContent)
return
}
}
// 处理请求
c.Next()
}
}
func checkGinCors(currentOrigin string) *GinCORSWhitelist {
if ginCorsConfig == nil {
return nil
}
for _, whitelist := range ginCorsConfig.Whitelist {
// 遍历配置中的跨域头,寻找匹配项
if currentOrigin == whitelist.AllowOrigin {
return &whitelist
}
}
return nil
}