Skip to content

Commit

Permalink
CORS middleware should compile allowOrigin regexp at creation.
Browse files Browse the repository at this point in the history
  • Loading branch information
aldas committed Nov 22, 2024
1 parent a973e3b commit 118c163
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ benchmark: ## Run benchmarks
help: ## Display this help screen
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

goversion ?= "1.19"
test_version: ## Run tests inside Docker with given version (defaults to 1.19 oldest supported). Example: make test_version goversion=1.19
goversion ?= "1.20"
test_version: ## Run tests inside Docker with given version (defaults to 1.20 oldest supported). Example: make test_version goversion=1.20
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
18 changes: 15 additions & 3 deletions middleware/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,25 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
config.AllowMethods = DefaultCORSConfig.AllowMethods
}

allowOriginPatterns := []string{}
allowOriginPatterns := make([]*regexp.Regexp, 0, len(config.AllowOrigins))
for _, origin := range config.AllowOrigins {
if origin == "*" {
continue // "*" is handled differently and does not need regexp
}
pattern := regexp.QuoteMeta(origin)
pattern = strings.ReplaceAll(pattern, "\\*", ".*")
pattern = strings.ReplaceAll(pattern, "\\?", ".")
pattern = "^" + pattern + "$"
allowOriginPatterns = append(allowOriginPatterns, pattern)

re, err := regexp.Compile(pattern)
if err != nil {
// this is to preserve previous behaviour - invalid patterns were just ignored.
// If we would turn this to panic, users with invalid patterns
// would have applications crashing in production due unrecovered panic.
// TODO: this should be turned to error/panic in `v5`
continue
}
allowOriginPatterns = append(allowOriginPatterns, re)
}

allowMethods := strings.Join(config.AllowMethods, ",")
Expand Down Expand Up @@ -239,7 +251,7 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
}
if checkPatterns {
for _, re := range allowOriginPatterns {
if match, _ := regexp.MatchString(re, origin); match {
if match := re.MatchString(origin); match {
allowOrigin = origin
break
}
Expand Down
12 changes: 12 additions & 0 deletions middleware/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ func TestCORS(t *testing.T) {
name: "ok, wildcard AllowedOrigin with no Origin header in request",
notExpectHeaders: map[string]string{echo.HeaderAccessControlAllowOrigin: ""},
},
{
name: "ok, invalid pattern is ignored",
givenMW: CORSWithConfig(CORSConfig{
AllowOrigins: []string{
"\xff", // Invalid UTF-8 makes regexp.Compile to error
"*.example.com",
},
}),
whenMethod: http.MethodOptions,
whenHeaders: map[string]string{echo.HeaderOrigin: "http://aaa.example.com"},
expectHeaders: map[string]string{echo.HeaderAccessControlAllowOrigin: "http://aaa.example.com"},
},
{
name: "ok, specific AllowOrigins and AllowCredentials",
givenMW: CORSWithConfig(CORSConfig{
Expand Down

0 comments on commit 118c163

Please sign in to comment.