package cors import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" ) type Options struct { Origin *[]string //传入空指针,表示允许"*", 传入空数组表示禁止跨域 Methods []string //Methods AllowedHeaders []string //AllowHeaders ExposedHeaders []string //exposeHeader Credentials bool //cookie MaxAge int64 //缓存MaxAge PreflightContinue bool //在遇到Options的时候,继续,而不是返回请求 OptionsSuccessStatus int //Options时,返回的状态码,默认204 } func configureOrigin(o *Options, c *gin.Context) map[string]string { reqOrigin := c.GetHeader("Origin") if o.Origin == nil { return map[string]string{"Access-Control-Allow-Origin": "*"} } headers := make(map[string]string) isAllowed := false for _, allowed := range *o.Origin { if allowed == reqOrigin { isAllowed = true break } } if isAllowed { headers["Access-Control-Allow-Origin"] = reqOrigin } else { headers["Access-Control-Allow-Origin"] = strconv.FormatBool(false) } headers["Vary"] = "Origin" return headers } func configureMethods(o *Options) map[string]string { headers := make(map[string]string) if len(o.Methods) > 0 { headers["Access-Control-Allow-Methods"] = strings.ToUpper(strings.Join(o.Methods, ",")) } return headers } func configureCredentials(o *Options) map[string]string { headers := make(map[string]string) if o.Credentials { headers["Access-Control-Allow-Credentials"] = strconv.FormatBool(true) } return headers } func configureAllowedHeaders(o *Options, c *gin.Context) map[string]string { headers := make(map[string]string) if len(o.AllowedHeaders) > 0 { headers["Access-Control-Allow-Headers"] = strings.Join(o.AllowedHeaders, ",") } return headers } func configureExposedHeaders(o *Options) map[string]string { var headers = make(map[string]string) if len(o.ExposedHeaders) > 0 { headers["Access-Control-Expose-Headers"] = strings.Join(o.ExposedHeaders, ",") } return headers } func configureMaxAge(o *Options) map[string]string { var headers = make(map[string]string) if o.MaxAge >= 0 { headers["Access-Control-Max-Age"] = strconv.FormatInt(o.MaxAge, 10) } return headers } func mergeMap(m ...map[string]string) map[string]string { r := make(map[string]string) for _, t := range m { for k, v := range t { r[k] = v } } return r } func applyHeader(c *gin.Context, h map[string]string) { for k, v := range h { c.Header(k, v) } } // Cors 跨域处理 func Cors(o *Options) gin.HandlerFunc { if o.OptionsSuccessStatus == 0 { o.OptionsSuccessStatus = http.StatusNoContent } return func(c *gin.Context) { method := c.Request.Method //c.Header("Access-Control-Allow-Origin", "*") //c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token,Authorization,Token,Content-Length,Etag,Content-Range,Accept-Ranges,User-Agent,Range,Bucket,Content-Disposition,Signature,X-Forwarded-For,X-Real-Ip") if method == "OPTIONS" { h := mergeMap( configureOrigin(o, c), configureCredentials(o), configureMethods(o), configureAllowedHeaders(o, c), configureMaxAge(o), configureExposedHeaders(o), ) applyHeader(c, h) if o.PreflightContinue { return } c.Header("Content-Length", "0") c.AbortWithStatus(o.OptionsSuccessStatus) return } h := mergeMap( configureOrigin(o, c), configureCredentials(o), configureExposedHeaders(o), ) applyHeader(c, h) } }