diff --git a/development/petshop-openapi-short-with-kusk-and-mock.yaml b/development/petshop-openapi-short-with-kusk-and-mock.yaml index 06f532248..dcc965674 100644 --- a/development/petshop-openapi-short-with-kusk-and-mock.yaml +++ b/development/petshop-openapi-short-with-kusk-and-mock.yaml @@ -192,7 +192,6 @@ paths: # Test CORS with: curl -v -H "Accept: application/json" -H "Origin: http://example.com" http://localhost:8080/petstore/api/v3/pet/2 # The result must be available access-control-allow-origin header. # Any other domain in Origin header will result in the absense of all CORS headers - # Note that OPTIONS usage is not directly supported, i.e. if you use "curl -XOPTIONS" this won't be routed unless you add options method to OpenAPI. cors: origins: - "http://example.com" diff --git a/envoy/config/config.go b/envoy/config/config.go index 9119b5af1..2c744ddef 100644 --- a/envoy/config/config.go +++ b/envoy/config/config.go @@ -4,6 +4,7 @@ package config import ( + "fmt" "regexp" "time" @@ -91,22 +92,47 @@ func (e *envoyConfiguration) AddRoute( timeout int64, idleTimeout int64, ) { - // match by this header - headerMatcher := []*route.HeaderMatcher{ - { - Name: ":method", - HeaderMatchSpecifier: &route.HeaderMatcher_StringMatch{ - StringMatch: &envoytypematcher.StringMatcher{ - MatchPattern: &envoytypematcher.StringMatcher_Exact{Exact: method}, - IgnoreCase: false, - }, + + // routeAction defines route parameters whose fields will be filled out further down + routeAction := &route.Route_Route{ + Route: &route.RouteAction{ + ClusterSpecifier: &route.RouteAction_Cluster{ + Cluster: clusterName, }, }, } - + // headerMatcher allows as to match route by method (:method header) + var headerMatcher []*route.HeaderMatcher + // If CORS specified, we add OPTIONS method to the route and enable CORS in the route + if corsPolicy != nil { + routeAction.Route.Cors = corsPolicy + // header matcher with OPTIONS or main method + headerMatcher = []*route.HeaderMatcher{ + { + Name: ":method", + HeaderMatchSpecifier: &route.HeaderMatcher_SafeRegexMatch{ + SafeRegexMatch: &envoytypematcher.RegexMatcher{ + EngineType: &envoytypematcher.RegexMatcher_GoogleRe2{}, + Regex: fmt.Sprintf("^OPTIONS|%s$", method), + }, + }, + }, + } + } else { + // otherwise simple exact match by method + headerMatcher = []*route.HeaderMatcher{ + { + Name: ":method", + HeaderMatchSpecifier: &route.HeaderMatcher_StringMatch{StringMatch: &envoytypematcher.StringMatcher{ + MatchPattern: &envoytypematcher.StringMatcher_Exact{ + Exact: method, + }, + }}, + }, + } + } var routeMatcher *route.RouteMatch - - // if regex - matcher is using RouteMatch_Regex with /{pattern} replaced by /([A-z0-9]+) regex + // if regex in the path - matcher is using RouteMatch_Regex with /{pattern} replaced by /([A-z0-9]+) regex // if simple path - RouteMatch_Path with path if rePathParams.MatchString(path) { replacementRegex := string(rePathParams.ReplaceAll([]byte(path), []byte("/([A-z0-9]+)"))) @@ -130,9 +156,8 @@ func (e *envoyConfiguration) AddRoute( } } // Trim prefix block rewrites path by regex in the route to cluster - var pathRewriteAction *envoytypematcher.RegexMatchAndSubstitute if trimPrefixRegex != "" { - pathRewriteAction = &envoytypematcher.RegexMatchAndSubstitute{ + routeAction.Route.RegexRewrite = &envoytypematcher.RegexMatchAndSubstitute{ Pattern: &envoytypematcher.RegexMatcher{ EngineType: &envoytypematcher.RegexMatcher_GoogleRe2{ GoogleRe2: &envoytypematcher.RegexMatcher_GoogleRE2{}, @@ -142,26 +167,11 @@ func (e *envoyConfiguration) AddRoute( Substitution: "/"} } - var routeTimeout *durationpb.Duration - var routeIdleTimeout *durationpb.Duration if timeout != 0 { - routeTimeout = &durationpb.Duration{Seconds: timeout} + routeAction.Route.Timeout = &durationpb.Duration{Seconds: timeout} } if idleTimeout != 0 { - routeIdleTimeout = &durationpb.Duration{Seconds: idleTimeout} - } - routeAction := &route.Route_Route{ - Route: &route.RouteAction{ - ClusterSpecifier: &route.RouteAction_Cluster{ - Cluster: clusterName, - }, - RegexRewrite: pathRewriteAction, - Timeout: routeTimeout, - IdleTimeout: routeIdleTimeout, - }, - } - if corsPolicy != nil { - routeAction.Route.Cors = corsPolicy + routeAction.Route.IdleTimeout = &durationpb.Duration{Seconds: idleTimeout} } // finally create the route and append it to the list rt := &route.Route{