Skip to content

Commit 45b197e

Browse files
appleboyarizz96
andauthored
feat: add regex support for origin validation in CORS configuration (#159)
* Allow regexp on AllowOrigins * Regexp AllowOrigins requires slashes at start and end * Merge branch 'gin-contrib/master' into feature/regexp-origin-match # Conflicts: # config.go # cors.go * Optimization * Add regexp origin tests * Fix regexp allowed origin schema check * refactor: refactor regular expression handling in schema validation - Define a new `regexpBasedOrigin` variable for compiling the regular expression - Replace inline regular expression compilation with the `regexpBasedOrigin` variable in `validateAllowedSchemas` function Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * refactor: simplify origin validation with precompiled regex - Define `originRegex` as a precompiled regular expression - Simplify origin validation logic using `originRegex` - Remove redundant regular expression compilation and matching logic Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * refactor: refactor codebase for improved readability and maintainability - Remove `exportloopref` linter from `.golangci.yml` - Update regex pattern in `config.go` to use backticks instead of double quotes - Refactor `validateOrigin` function for better readability by splitting a long line into two lines Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> --------- Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-authored-by: arizz96 <arizz96@gmail.com>
1 parent dac7b69 commit 45b197e

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

.golangci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ linters:
77
- dogsled
88
- dupl
99
- errcheck
10-
- exportloopref
1110
- exhaustive
1211
- gochecknoinits
1312
- goconst

config.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cors
22

33
import (
44
"net/http"
5+
"regexp"
56
"strings"
67

78
"github.com/gin-gonic/gin"
@@ -122,21 +123,32 @@ func (cors *cors) isOriginValid(c *gin.Context, origin string) bool {
122123
return valid
123124
}
124125

126+
var originRegex = regexp.MustCompile(`^/(.+)/[gimuy]?$`)
127+
125128
func (cors *cors) validateOrigin(origin string) bool {
126129
if cors.allowAllOrigins {
127130
return true
128131
}
132+
129133
for _, value := range cors.allowOrigins {
130-
if value == origin {
134+
if !originRegex.MatchString(value) && value == origin {
135+
return true
136+
}
137+
138+
if originRegex.MatchString(value) &&
139+
regexp.MustCompile(originRegex.FindStringSubmatch(value)[1]).MatchString(origin) {
131140
return true
132141
}
133142
}
143+
134144
if len(cors.wildcardOrigins) > 0 && cors.validateWildcardOrigin(origin) {
135145
return true
136146
}
147+
137148
if cors.allowOriginFunc != nil {
138149
return cors.allowOriginFunc(origin)
139150
}
151+
140152
return false
141153
}
142154

cors.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cors
33
import (
44
"errors"
55
"fmt"
6+
"regexp"
67
"strings"
78
"time"
89

@@ -103,8 +104,17 @@ func (c Config) getAllowedSchemas() []string {
103104
return allowedSchemas
104105
}
105106

107+
var regexpBasedOrigin = regexp.MustCompile(`^\/(.+)\/[gimuy]?$`)
108+
106109
func (c Config) validateAllowedSchemas(origin string) bool {
107110
allowedSchemas := c.getAllowedSchemas()
111+
112+
if regexpBasedOrigin.MatchString(origin) {
113+
// Normalize regexp-based origins
114+
origin = regexpBasedOrigin.FindStringSubmatch(origin)[1]
115+
origin = strings.Replace(origin, "?", "", 1)
116+
}
117+
108118
for _, schema := range allowedSchemas {
109119
if strings.HasPrefix(origin, schema) {
110120
return true

cors_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,21 @@ func TestBadConfig(t *testing.T) {
112112
AllowOrigins: []string{"google.com"},
113113
})
114114
})
115+
assert.Panics(t, func() {
116+
New(Config{
117+
AllowOrigins: []string{"/http://google.com"},
118+
})
119+
})
120+
assert.Panics(t, func() {
121+
New(Config{
122+
AllowOrigins: []string{"http?://google.com"},
123+
})
124+
})
125+
assert.Panics(t, func() {
126+
New(Config{
127+
AllowOrigins: []string{"http?://google.com/g"},
128+
})
129+
})
115130
}
116131

117132
func TestNormalize(t *testing.T) {
@@ -296,6 +311,15 @@ func TestValidateOrigin(t *testing.T) {
296311
assert.True(t, cors.validateOrigin("https://google.com"))
297312
assert.True(t, cors.validateOrigin("example.com"))
298313
assert.True(t, cors.validateOrigin("chrome-extension://random-extension-id"))
314+
315+
cors = newCors(Config{
316+
AllowOrigins: []string{"/https?://(?:.+\\.)?google\\.com/g"},
317+
})
318+
assert.True(t, cors.validateOrigin("http://google.com"))
319+
assert.True(t, cors.validateOrigin("https://google.com"))
320+
assert.True(t, cors.validateOrigin("https://maps.google.com"))
321+
assert.True(t, cors.validateOrigin("https://maps.test.google.com"))
322+
assert.False(t, cors.validateOrigin("https://maps.google.it"))
299323
}
300324

301325
func TestValidateTauri(t *testing.T) {

0 commit comments

Comments
 (0)