github.com/gofiber/fiber/v2@v2.47.0/middleware/cors/cors.go (about) 1 package cors 2 3 import ( 4 "log" 5 "strconv" 6 "strings" 7 8 "github.com/gofiber/fiber/v2" 9 ) 10 11 // Config defines the config for middleware. 12 type Config struct { 13 // Next defines a function to skip this middleware when returned true. 14 // 15 // Optional. Default: nil 16 Next func(c *fiber.Ctx) bool 17 18 // AllowOriginsFunc defines a function that will set the 'access-control-allow-origin' 19 // response header to the 'origin' request header when returned true. 20 // 21 // Optional. Default: nil 22 AllowOriginsFunc func(origin string) bool 23 24 // AllowOrigin defines a list of origins that may access the resource. 25 // 26 // Optional. Default value "*" 27 AllowOrigins string 28 29 // AllowMethods defines a list methods allowed when accessing the resource. 30 // This is used in response to a preflight request. 31 // 32 // Optional. Default value "GET,POST,HEAD,PUT,DELETE,PATCH" 33 AllowMethods string 34 35 // AllowHeaders defines a list of request headers that can be used when 36 // making the actual request. This is in response to a preflight request. 37 // 38 // Optional. Default value "". 39 AllowHeaders string 40 41 // AllowCredentials indicates whether or not the response to the request 42 // can be exposed when the credentials flag is true. When used as part of 43 // a response to a preflight request, this indicates whether or not the 44 // actual request can be made using credentials. 45 // 46 // Optional. Default value false. 47 AllowCredentials bool 48 49 // ExposeHeaders defines a whitelist headers that clients are allowed to 50 // access. 51 // 52 // Optional. Default value "". 53 ExposeHeaders string 54 55 // MaxAge indicates how long (in seconds) the results of a preflight request 56 // can be cached. 57 // 58 // Optional. Default value 0. 59 MaxAge int 60 } 61 62 // ConfigDefault is the default config 63 var ConfigDefault = Config{ 64 Next: nil, 65 AllowOriginsFunc: nil, 66 AllowOrigins: "*", 67 AllowMethods: strings.Join([]string{ 68 fiber.MethodGet, 69 fiber.MethodPost, 70 fiber.MethodHead, 71 fiber.MethodPut, 72 fiber.MethodDelete, 73 fiber.MethodPatch, 74 }, ","), 75 AllowHeaders: "", 76 AllowCredentials: false, 77 ExposeHeaders: "", 78 MaxAge: 0, 79 } 80 81 // New creates a new middleware handler 82 func New(config ...Config) fiber.Handler { 83 // Set default config 84 cfg := ConfigDefault 85 86 // Override config if provided 87 if len(config) > 0 { 88 cfg = config[0] 89 90 // Set default values 91 if cfg.AllowMethods == "" { 92 cfg.AllowMethods = ConfigDefault.AllowMethods 93 } 94 if cfg.AllowOrigins == "" { 95 cfg.AllowOrigins = ConfigDefault.AllowOrigins 96 } 97 } 98 99 // Warning logs if both AllowOrigins and AllowOriginsFunc are set 100 if cfg.AllowOrigins != ConfigDefault.AllowOrigins && cfg.AllowOriginsFunc != nil { 101 log.Printf("[Warning] - [CORS] Both 'AllowOrigins' and 'AllowOriginsFunc' have been defined.\n") 102 } 103 104 // Convert string to slice 105 allowOrigins := strings.Split(strings.ReplaceAll(cfg.AllowOrigins, " ", ""), ",") 106 107 // Strip white spaces 108 allowMethods := strings.ReplaceAll(cfg.AllowMethods, " ", "") 109 allowHeaders := strings.ReplaceAll(cfg.AllowHeaders, " ", "") 110 exposeHeaders := strings.ReplaceAll(cfg.ExposeHeaders, " ", "") 111 112 // Convert int to string 113 maxAge := strconv.Itoa(cfg.MaxAge) 114 115 // Return new handler 116 return func(c *fiber.Ctx) error { 117 // Don't execute middleware if Next returns true 118 if cfg.Next != nil && cfg.Next(c) { 119 return c.Next() 120 } 121 122 // Get origin header 123 origin := c.Get(fiber.HeaderOrigin) 124 allowOrigin := "" 125 126 // Check allowed origins 127 for _, o := range allowOrigins { 128 if o == "*" { 129 allowOrigin = "*" 130 break 131 } 132 if o == origin { 133 allowOrigin = o 134 break 135 } 136 if matchSubdomain(origin, o) { 137 allowOrigin = origin 138 break 139 } 140 } 141 142 // Run AllowOriginsFunc if the logic for 143 // handling the value in 'AllowOrigins' does 144 // not result in allowOrigin being set. 145 if (allowOrigin == "" || allowOrigin == ConfigDefault.AllowOrigins) && cfg.AllowOriginsFunc != nil { 146 if cfg.AllowOriginsFunc(origin) { 147 allowOrigin = origin 148 } 149 } 150 151 // Simple request 152 if c.Method() != fiber.MethodOptions { 153 c.Vary(fiber.HeaderOrigin) 154 c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin) 155 156 if cfg.AllowCredentials { 157 c.Set(fiber.HeaderAccessControlAllowCredentials, "true") 158 } 159 if exposeHeaders != "" { 160 c.Set(fiber.HeaderAccessControlExposeHeaders, exposeHeaders) 161 } 162 return c.Next() 163 } 164 165 // Preflight request 166 c.Vary(fiber.HeaderOrigin) 167 c.Vary(fiber.HeaderAccessControlRequestMethod) 168 c.Vary(fiber.HeaderAccessControlRequestHeaders) 169 c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin) 170 c.Set(fiber.HeaderAccessControlAllowMethods, allowMethods) 171 172 // Set Allow-Credentials if set to true 173 if cfg.AllowCredentials { 174 c.Set(fiber.HeaderAccessControlAllowCredentials, "true") 175 } 176 177 // Set Allow-Headers if not empty 178 if allowHeaders != "" { 179 c.Set(fiber.HeaderAccessControlAllowHeaders, allowHeaders) 180 } else { 181 h := c.Get(fiber.HeaderAccessControlRequestHeaders) 182 if h != "" { 183 c.Set(fiber.HeaderAccessControlAllowHeaders, h) 184 } 185 } 186 187 // Set MaxAge is set 188 if cfg.MaxAge > 0 { 189 c.Set(fiber.HeaderAccessControlMaxAge, maxAge) 190 } 191 192 // Send 204 No Content 193 return c.SendStatus(fiber.StatusNoContent) 194 } 195 }