package cors import ( "net/http" "github.com/gin-gonic/gin" ) type cors struct { allowAllOrigins bool allowCredentials bool allowOriginFunc func(string) bool allowOrigins []string exposeHeaders []string normalHeaders http.Header preflightHeaders http.Header } var ( DefaultSchemas = []string{ "http://", "https://", } ExtensionSchemas = []string{ "chrome-extension://", "safari-extension://", "moz-extension://", "ms-browser-extension://", } ) func newCors(config Config) *cors { if err := config.Validate(); err != nil { panic(err.Error()) } return &cors{ allowOriginFunc: config.AllowOriginFunc, allowAllOrigins: config.AllowAllOrigins, allowCredentials: config.AllowCredentials, allowOrigins: normalize(config.AllowOrigins), normalHeaders: generateNormalHeaders(config), preflightHeaders: generatePreflightHeaders(config), } } func (cors *cors) applyCors(c *gin.Context) { origin := c.Request.Header.Get("Origin") if len(origin) == 0 { // request is not a CORS request return } host := c.Request.Header.Get("Host") if origin == "http://"+host || origin == "https://"+host { // request is not a CORS request but have origin header. // for example, use fetch api return } if !cors.validateOrigin(origin) { c.AbortWithStatus(http.StatusForbidden) return } if c.Request.Method == "OPTIONS" { cors.handlePreflight(c) defer c.AbortWithStatus(200) } else { cors.handleNormal(c) } if !cors.allowAllOrigins { c.Header("Access-Control-Allow-Origin", origin) } } func (cors *cors) validateOrigin(origin string) bool { if cors.allowAllOrigins { return true } for _, value := range cors.allowOrigins { if value == origin { return true } } if cors.allowOriginFunc != nil { return cors.allowOriginFunc(origin) } return false } func (cors *cors) handlePreflight(c *gin.Context) { header := c.Writer.Header() for key, value := range cors.preflightHeaders { header[key] = value } } func (cors *cors) handleNormal(c *gin.Context) { header := c.Writer.Header() for key, value := range cors.normalHeaders { header[key] = value } }