134 lines
3.5 KiB
Go
134 lines
3.5 KiB
Go
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)
|
|
}
|
|
}
|