Renames some options
This commit is contained in:
parent
4b9ae1e081
commit
ee70b8845a
16
config.go
16
config.go
@ -8,9 +8,9 @@ import (
|
|||||||
|
|
||||||
type cors struct {
|
type cors struct {
|
||||||
allowAllOrigins bool
|
allowAllOrigins bool
|
||||||
allowedOriginFunc func(string) bool
|
allowOriginFunc func(string) bool
|
||||||
allowedOrigins []string
|
allowOrigins []string
|
||||||
exposedHeaders []string
|
exposeHeaders []string
|
||||||
normalHeaders http.Header
|
normalHeaders http.Header
|
||||||
preflightHeaders http.Header
|
preflightHeaders http.Header
|
||||||
}
|
}
|
||||||
@ -20,9 +20,9 @@ func newCors(config Config) *cors {
|
|||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
return &cors{
|
return &cors{
|
||||||
allowedOriginFunc: config.AllowOriginFunc,
|
allowOriginFunc: config.AllowOriginFunc,
|
||||||
allowAllOrigins: config.AllowAllOrigins,
|
allowAllOrigins: config.AllowAllOrigins,
|
||||||
allowedOrigins: normalize(config.AllowedOrigins),
|
allowOrigins: normalize(config.AllowOrigins),
|
||||||
normalHeaders: generateNormalHeaders(config),
|
normalHeaders: generateNormalHeaders(config),
|
||||||
preflightHeaders: generatePreflightHeaders(config),
|
preflightHeaders: generatePreflightHeaders(config),
|
||||||
}
|
}
|
||||||
@ -54,13 +54,13 @@ func (cors *cors) validateOrigin(origin string) bool {
|
|||||||
if cors.allowAllOrigins {
|
if cors.allowAllOrigins {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, value := range cors.allowedOrigins {
|
for _, value := range cors.allowOrigins {
|
||||||
if value == origin {
|
if value == origin {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cors.allowedOriginFunc != nil {
|
if cors.allowOriginFunc != nil {
|
||||||
return cors.allowedOriginFunc(origin)
|
return cors.allowOriginFunc(origin)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
41
cors.go
41
cors.go
@ -14,7 +14,7 @@ type Config struct {
|
|||||||
// AllowedOrigins is a list of origins a cross-domain request can be executed from.
|
// AllowedOrigins is a list of origins a cross-domain request can be executed from.
|
||||||
// If the special "*" value is present in the list, all origins will be allowed.
|
// If the special "*" value is present in the list, all origins will be allowed.
|
||||||
// Default value is ["*"]
|
// Default value is ["*"]
|
||||||
AllowedOrigins []string
|
AllowOrigins []string
|
||||||
|
|
||||||
// AllowOriginFunc is a custom function to validate the origin. It take the origin
|
// AllowOriginFunc is a custom function to validate the origin. It take the origin
|
||||||
// as argument and returns true if allowed or false otherwise. If this option is
|
// as argument and returns true if allowed or false otherwise. If this option is
|
||||||
@ -23,47 +23,47 @@ type Config struct {
|
|||||||
|
|
||||||
// AllowedMethods is a list of methods the client is allowed to use with
|
// AllowedMethods is a list of methods the client is allowed to use with
|
||||||
// cross-domain requests. Default value is simple methods (GET and POST)
|
// cross-domain requests. Default value is simple methods (GET and POST)
|
||||||
AllowedMethods []string
|
AllowMethods []string
|
||||||
|
|
||||||
// AllowedHeaders is list of non simple headers the client is allowed to use with
|
// AllowedHeaders is list of non simple headers the client is allowed to use with
|
||||||
// cross-domain requests.
|
// cross-domain requests.
|
||||||
// If the special "*" value is present in the list, all headers will be allowed.
|
// If the special "*" value is present in the list, all headers will be allowed.
|
||||||
// Default value is [] but "Origin" is always appended to the list.
|
// Default value is [] but "Origin" is always appended to the list.
|
||||||
AllowedHeaders []string
|
AllowHeaders []string
|
||||||
|
|
||||||
// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
|
|
||||||
// API specification
|
|
||||||
ExposedHeaders []string
|
|
||||||
|
|
||||||
// AllowCredentials indicates whether the request can include user credentials like
|
// AllowCredentials indicates whether the request can include user credentials like
|
||||||
// cookies, HTTP authentication or client side SSL certificates.
|
// cookies, HTTP authentication or client side SSL certificates.
|
||||||
AllowCredentials bool
|
AllowCredentials bool
|
||||||
|
|
||||||
|
// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
|
||||||
|
// API specification
|
||||||
|
ExposeHeaders []string
|
||||||
|
|
||||||
// MaxAge indicates how long (in seconds) the results of a preflight request
|
// MaxAge indicates how long (in seconds) the results of a preflight request
|
||||||
// can be cached
|
// can be cached
|
||||||
MaxAge time.Duration
|
MaxAge time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) AddAllowedMethods(methods ...string) {
|
func (c *Config) AddAllowMethods(methods ...string) {
|
||||||
c.AllowedMethods = append(c.AllowedMethods, methods...)
|
c.AllowMethods = append(c.AllowMethods, methods...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) AddAllowedHeaders(headers ...string) {
|
func (c *Config) AddAllowHeaders(headers ...string) {
|
||||||
c.AllowedHeaders = append(c.AllowedHeaders, headers...)
|
c.AllowHeaders = append(c.AllowHeaders, headers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) AddExposedHeaders(headers ...string) {
|
func (c *Config) AddExposeHeaders(headers ...string) {
|
||||||
c.ExposedHeaders = append(c.ExposedHeaders, headers...)
|
c.ExposeHeaders = append(c.ExposeHeaders, headers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) Validate() error {
|
func (c Config) Validate() error {
|
||||||
if c.AllowAllOrigins && (c.AllowOriginFunc != nil || len(c.AllowedOrigins) > 0) {
|
if c.AllowAllOrigins && (c.AllowOriginFunc != nil || len(c.AllowOrigins) > 0) {
|
||||||
return errors.New("conflict settings: all origins are allowed. AllowOriginFunc or AllowedOrigins is not needed")
|
return errors.New("conflict settings: all origins are allowed. AllowOriginFunc or AllowedOrigins is not needed")
|
||||||
}
|
}
|
||||||
if !c.AllowAllOrigins && c.AllowOriginFunc == nil && len(c.AllowedOrigins) == 0 {
|
if !c.AllowAllOrigins && c.AllowOriginFunc == nil && len(c.AllowOrigins) == 0 {
|
||||||
return errors.New("conflict settings: all origins disabled")
|
return errors.New("conflict settings: all origins disabled")
|
||||||
}
|
}
|
||||||
for _, origin := range c.AllowedOrigins {
|
for _, origin := range c.AllowOrigins {
|
||||||
if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
|
if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
|
||||||
return errors.New("bad origin: origins must include http:// or https://")
|
return errors.New("bad origin: origins must include http:// or https://")
|
||||||
}
|
}
|
||||||
@ -73,16 +73,17 @@ func (c Config) Validate() error {
|
|||||||
|
|
||||||
func DefaultConfig() Config {
|
func DefaultConfig() Config {
|
||||||
return Config{
|
return Config{
|
||||||
AllowAllOrigins: true,
|
AllowMethods: []string{"GET", "POST", "PUT", "HEAD"},
|
||||||
AllowedMethods: []string{"GET", "POST", "PUT", "HEAD"},
|
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type"},
|
||||||
AllowedHeaders: []string{"Content-Type"},
|
|
||||||
AllowCredentials: false,
|
AllowCredentials: false,
|
||||||
MaxAge: 12 * time.Hour,
|
MaxAge: 12 * time.Hour,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Default() gin.HandlerFunc {
|
func Default() gin.HandlerFunc {
|
||||||
return New(DefaultConfig())
|
config := DefaultConfig()
|
||||||
|
config.AllowAllOrigins = true
|
||||||
|
return New(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config Config) gin.HandlerFunc {
|
func New(config Config) gin.HandlerFunc {
|
||||||
|
44
cors_test.go
44
cors_test.go
@ -44,7 +44,7 @@ func TestBadConfig(t *testing.T) {
|
|||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
New(Config{
|
New(Config{
|
||||||
AllowAllOrigins: true,
|
AllowAllOrigins: true,
|
||||||
AllowedOrigins: []string{"http://google.com"},
|
AllowOrigins: []string{"http://google.com"},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
@ -55,7 +55,7 @@ func TestBadConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
New(Config{
|
New(Config{
|
||||||
AllowedOrigins: []string{"google.com"},
|
AllowOrigins: []string{"google.com"},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -101,9 +101,9 @@ func TestGenerateNormalHeaders_AllowCredentials(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateNormalHeaders_ExposedHeaders(t *testing.T) {
|
func TestGenerateNormalHeaders_ExposedHeaders(t *testing.T) {
|
||||||
header := generateNormalHeaders(Config{
|
header := generateNormalHeaders(Config{
|
||||||
ExposedHeaders: []string{"X-user", "xPassword"},
|
ExposeHeaders: []string{"X-user", "xPassword"},
|
||||||
})
|
})
|
||||||
assert.Equal(t, header.Get("Access-Control-Expose-Headers"), "x-user, xpassword")
|
assert.Equal(t, header.Get("Access-Control-Expose-Headers"), "x-user,xpassword")
|
||||||
assert.Equal(t, header.Get("Vary"), "Origin")
|
assert.Equal(t, header.Get("Vary"), "Origin")
|
||||||
assert.Len(t, header, 2)
|
assert.Len(t, header, 2)
|
||||||
}
|
}
|
||||||
@ -135,18 +135,18 @@ func TestGeneratePreflightHeaders_AllowCredentials(t *testing.T) {
|
|||||||
|
|
||||||
func TestGeneratePreflightHeaders_AllowedMethods(t *testing.T) {
|
func TestGeneratePreflightHeaders_AllowedMethods(t *testing.T) {
|
||||||
header := generatePreflightHeaders(Config{
|
header := generatePreflightHeaders(Config{
|
||||||
AllowedMethods: []string{"GET ", "post", "PUT", " put "},
|
AllowMethods: []string{"GET ", "post", "PUT", " put "},
|
||||||
})
|
})
|
||||||
assert.Equal(t, header.Get("Access-Control-Allow-Methods"), "get, post, put")
|
assert.Equal(t, header.Get("Access-Control-Allow-Methods"), "get,post,put")
|
||||||
assert.Equal(t, header.Get("Vary"), "Origin")
|
assert.Equal(t, header.Get("Vary"), "Origin")
|
||||||
assert.Len(t, header, 2)
|
assert.Len(t, header, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGeneratePreflightHeaders_AllowedHeaders(t *testing.T) {
|
func TestGeneratePreflightHeaders_AllowedHeaders(t *testing.T) {
|
||||||
header := generatePreflightHeaders(Config{
|
header := generatePreflightHeaders(Config{
|
||||||
AllowedHeaders: []string{"X-user", "Content-Type"},
|
AllowHeaders: []string{"X-user", "Content-Type"},
|
||||||
})
|
})
|
||||||
assert.Equal(t, header.Get("Access-Control-Allow-Headers"), "x-user, content-type")
|
assert.Equal(t, header.Get("Access-Control-Allow-Headers"), "x-user,content-type")
|
||||||
assert.Equal(t, header.Get("Vary"), "Origin")
|
assert.Equal(t, header.Get("Vary"), "Origin")
|
||||||
assert.Len(t, header, 2)
|
assert.Len(t, header, 2)
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ func TestValidateOrigin(t *testing.T) {
|
|||||||
assert.True(t, cors.validateOrigin("example.com"))
|
assert.True(t, cors.validateOrigin("example.com"))
|
||||||
|
|
||||||
cors = newCors(Config{
|
cors = newCors(Config{
|
||||||
AllowedOrigins: []string{"https://google.com", "https://github.com"},
|
AllowOrigins: []string{"https://google.com", "https://github.com"},
|
||||||
AllowOriginFunc: func(origin string) bool {
|
AllowOriginFunc: func(origin string) bool {
|
||||||
return (origin == "http://news.ycombinator.com")
|
return (origin == "http://news.ycombinator.com")
|
||||||
},
|
},
|
||||||
@ -184,10 +184,10 @@ func TestValidateOrigin(t *testing.T) {
|
|||||||
|
|
||||||
func TestPassesAllowedOrigins(t *testing.T) {
|
func TestPassesAllowedOrigins(t *testing.T) {
|
||||||
router := newTestRouter(Config{
|
router := newTestRouter(Config{
|
||||||
AllowedOrigins: []string{"http://google.com"},
|
AllowOrigins: []string{"http://google.com"},
|
||||||
AllowedMethods: []string{" GeT ", "get", "post", "PUT ", "Head", "POST"},
|
AllowMethods: []string{" GeT ", "get", "post", "PUT ", "Head", "POST"},
|
||||||
AllowedHeaders: []string{"Content-type", "timeStamp "},
|
AllowHeaders: []string{"Content-type", "timeStamp "},
|
||||||
ExposedHeaders: []string{"Data", "x-User"},
|
ExposeHeaders: []string{"Data", "x-User"},
|
||||||
AllowCredentials: true,
|
AllowCredentials: true,
|
||||||
MaxAge: 12 * time.Hour,
|
MaxAge: 12 * time.Hour,
|
||||||
AllowOriginFunc: func(origin string) bool {
|
AllowOriginFunc: func(origin string) bool {
|
||||||
@ -207,7 +207,7 @@ func TestPassesAllowedOrigins(t *testing.T) {
|
|||||||
assert.Equal(t, w.Body.String(), "get")
|
assert.Equal(t, w.Body.String(), "get")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "http://google.com")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "http://google.com")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "true")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "true")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "data, x-user")
|
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "data,x-user")
|
||||||
|
|
||||||
// deny CORS request
|
// deny CORS request
|
||||||
w = performRequest(router, "GET", "https://google.com")
|
w = performRequest(router, "GET", "https://google.com")
|
||||||
@ -221,8 +221,8 @@ func TestPassesAllowedOrigins(t *testing.T) {
|
|||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, w.Code, 200)
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "http://github.com")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "http://github.com")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "true")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Credentials"), "true")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "get, post, put, head")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "get,post,put,head")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "content-type, timestamp")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "content-type,timestamp")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "43200")
|
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "43200")
|
||||||
|
|
||||||
// deny CORS prefligh request
|
// deny CORS prefligh request
|
||||||
@ -238,9 +238,9 @@ func TestPassesAllowedOrigins(t *testing.T) {
|
|||||||
func TestPassesAllowedAllOrigins(t *testing.T) {
|
func TestPassesAllowedAllOrigins(t *testing.T) {
|
||||||
router := newTestRouter(Config{
|
router := newTestRouter(Config{
|
||||||
AllowAllOrigins: true,
|
AllowAllOrigins: true,
|
||||||
AllowedMethods: []string{" Patch ", "get", "post", "POST"},
|
AllowMethods: []string{" Patch ", "get", "post", "POST"},
|
||||||
AllowedHeaders: []string{"Content-type", " testheader "},
|
AllowHeaders: []string{"Content-type", " testheader "},
|
||||||
ExposedHeaders: []string{"Data2", "x-User2"},
|
ExposeHeaders: []string{"Data2", "x-User2"},
|
||||||
AllowCredentials: false,
|
AllowCredentials: false,
|
||||||
MaxAge: 10 * time.Hour,
|
MaxAge: 10 * time.Hour,
|
||||||
})
|
})
|
||||||
@ -256,15 +256,15 @@ func TestPassesAllowedAllOrigins(t *testing.T) {
|
|||||||
w = performRequest(router, "POST", "example.com")
|
w = performRequest(router, "POST", "example.com")
|
||||||
assert.Equal(t, w.Body.String(), "post")
|
assert.Equal(t, w.Body.String(), "post")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "data2, x-user2")
|
assert.Equal(t, w.Header().Get("Access-Control-Expose-Headers"), "data2,x-user2")
|
||||||
assert.Empty(t, w.Header().Get("Access-Control-Allow-Credentials"))
|
assert.Empty(t, w.Header().Get("Access-Control-Allow-Credentials"))
|
||||||
|
|
||||||
// allowed CORS prefligh request
|
// allowed CORS prefligh request
|
||||||
w = performRequest(router, "OPTIONS", "https://facebook.com")
|
w = performRequest(router, "OPTIONS", "https://facebook.com")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, w.Code, 200)
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Origin"), "*")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "patch, get, post")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Methods"), "patch,get,post")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "content-type, testheader")
|
assert.Equal(t, w.Header().Get("Access-Control-Allow-Headers"), "content-type,testheader")
|
||||||
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "36000")
|
assert.Equal(t, w.Header().Get("Access-Control-Max-Age"), "36000")
|
||||||
assert.Empty(t, w.Header().Get("Access-Control-Allow-Credentials"))
|
assert.Empty(t, w.Header().Get("Access-Control-Allow-Credentials"))
|
||||||
}
|
}
|
||||||
|
18
utils.go
18
utils.go
@ -12,9 +12,9 @@ func generateNormalHeaders(c Config) http.Header {
|
|||||||
if c.AllowCredentials {
|
if c.AllowCredentials {
|
||||||
headers.Set("Access-Control-Allow-Credentials", "true")
|
headers.Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
}
|
||||||
if len(c.ExposedHeaders) > 0 {
|
if len(c.ExposeHeaders) > 0 {
|
||||||
exposedHeaders := normalize(c.ExposedHeaders)
|
exposeHeaders := normalize(c.ExposeHeaders)
|
||||||
headers.Set("Access-Control-Expose-Headers", strings.Join(exposedHeaders, ", "))
|
headers.Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||||
}
|
}
|
||||||
if c.AllowAllOrigins {
|
if c.AllowAllOrigins {
|
||||||
headers.Set("Access-Control-Allow-Origin", "*")
|
headers.Set("Access-Control-Allow-Origin", "*")
|
||||||
@ -29,14 +29,14 @@ func generatePreflightHeaders(c Config) http.Header {
|
|||||||
if c.AllowCredentials {
|
if c.AllowCredentials {
|
||||||
headers.Set("Access-Control-Allow-Credentials", "true")
|
headers.Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
}
|
||||||
if len(c.AllowedMethods) > 0 {
|
if len(c.AllowMethods) > 0 {
|
||||||
allowedMethods := normalize(c.AllowedMethods)
|
allowMethods := normalize(c.AllowMethods)
|
||||||
value := strings.Join(allowedMethods, ", ")
|
value := strings.Join(allowMethods, ",")
|
||||||
headers.Set("Access-Control-Allow-Methods", value)
|
headers.Set("Access-Control-Allow-Methods", value)
|
||||||
}
|
}
|
||||||
if len(c.AllowedHeaders) > 0 {
|
if len(c.AllowHeaders) > 0 {
|
||||||
allowedHeaders := normalize(c.AllowedHeaders)
|
allowHeaders := normalize(c.AllowHeaders)
|
||||||
value := strings.Join(allowedHeaders, ", ")
|
value := strings.Join(allowHeaders, ",")
|
||||||
headers.Set("Access-Control-Allow-Headers", value)
|
headers.Set("Access-Control-Allow-Headers", value)
|
||||||
}
|
}
|
||||||
if c.MaxAge > time.Duration(0) {
|
if c.MaxAge > time.Duration(0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user