Skip to content

Commit

Permalink
Merge pull request #2391 from sgayangi/sgayangi-mirror-redirect-filters
Browse files Browse the repository at this point in the history
Add support for RequestMirror and RequestRedirect filters
  • Loading branch information
sgayangi authored Jun 25, 2024
2 parents 3115de5 + 25f6683 commit 8bfa83f
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 69 deletions.
7 changes: 7 additions & 0 deletions adapter/internal/oasparser/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ const (
ActionRewriteMethod string = "REWRITE_RESOURCE_METHOD"
ActionInterceptorService string = "CALL_INTERCEPTOR_SERVICE"
ActionRewritePath string = "REWRITE_RESOURCE_PATH"
ActionRedirectRequest string = "REDIRECT_REQUEST"
ActionMirrorRequest string = "MIRROR_REQUEST"

PolicyRequestInterceptor string = "PolicyRequestInterceptor"
PolicyResponseInterceptor string = "PolicyResponseInterceptor"
Expand All @@ -90,6 +92,11 @@ const (
HeaderValue string = "headerValue"
CurrentMethod string = "currentMethod"
UpdatedMethod string = "updatedMethod"
RedirectScheme string = "scheme"
RedirectHostname string = "hostname"
RedirectPath string = "path"
RedirectPort string = "port"
RedirectStatusCode string = "statusCode"
)

// API Type Constants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestCreateRoute(t *testing.T) {

resourceWithGet := model.CreateMinimalDummyResourceForTests("/xWso2BasePath/resourcePath",
[]*model.Operation{model.NewOperationWithPolicies("GET", policies)},
"resource_operation_id", []model.Endpoint{endpoint}, true)
"resource_operation_id", []model.Endpoint{endpoint}, true, false)
clusterName := "resource_operation_id"
hostRewriteSpecifier := &routev3.RouteAction_AutoHostRewrite{
AutoHostRewrite: &wrapperspb.BoolValue{
Expand Down Expand Up @@ -143,7 +143,7 @@ func TestCreateRouteClusterSpecifier(t *testing.T) {
RawURL: "http://abc.com",
}
resourceWithGet := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{model.NewOperation("GET", nil, nil)},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)

route, err := createRoutes(generateRouteCreateParamsForUnitTests(title, apiType, vHost, xWso2BasePath, version, endpointBasePath,
&resourceWithGet, clusterName, nil, false))
Expand Down Expand Up @@ -174,7 +174,7 @@ func TestCreateRouteExtAuthzContext(t *testing.T) {
RawURL: "http://abc.com",
}
resourceWithGet := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{model.NewOperation("GET", nil, nil)},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)

route, err := createRoutes(generateRouteCreateParamsForUnitTests(title, apiType, vHost, xWso2BasePath, version,
endpointBasePath, &resourceWithGet, clusterName, nil, false))
Expand Down Expand Up @@ -571,7 +571,7 @@ func TestGetCorsPolicy(t *testing.T) {
assert.Empty(t, corsPolicy3.GetAllowCredentials(), "Allow Credential property should not be assigned.")

resourceWithGet := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{model.NewOperation("GET", nil, nil)},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)

// Route without CORS configuration
routeWithoutCors, err := createRoutes(generateRouteCreateParamsForUnitTests("test", "HTTP", "localhost", "/test", "1.0.0", "/test",
Expand Down
1 change: 1 addition & 0 deletions adapter/internal/oasparser/envoyconf/internal_dtos.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type routeCreateParams struct {
apiProperties []dpv1alpha2.Property
environment string
envType string
mirrorClusterNames map[string][]string
}

// RatelimitCriteria criterias of rate limiting
Expand Down
8 changes: 4 additions & 4 deletions adapter/internal/oasparser/envoyconf/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,13 @@ func testCreateRoutesForUnitTests(t *testing.T) []*routev3.Route {
operationPost := model.NewOperation("POST", nil, nil)
operationPut := model.NewOperation("PUT", nil, nil)
resourceWithGet := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{operationGet},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)
resourceWithPost := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{operationPost},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)
resourceWithPut := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{operationPut},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)
resourceWithMultipleOperations := model.CreateMinimalDummyResourceForTests("/resourcePath", []*model.Operation{operationGet, operationPut},
"resource_operation_id", []model.Endpoint{endpoint}, false)
"resource_operation_id", []model.Endpoint{endpoint}, false, false)

route1, err := createRoutes(generateRouteCreateParamsForUnitTests("test", "HTTP", "localhost", "/test", "1.0.0", "/test",
&resourceWithGet, "test-cluster", corsConfigModel3, false))
Expand Down
68 changes: 65 additions & 3 deletions adapter/internal/oasparser/envoyconf/routes_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,14 @@ import (
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

func generateRouteConfig(routeName string, match *routev3.RouteMatch, action *routev3.Route_Route,
func generateRouteConfig(routeName string, match *routev3.RouteMatch, action *routev3.Route_Route, redirectAction *routev3.Route_Redirect,
metadata *corev3.Metadata, decorator *routev3.Decorator, typedPerFilterConfig map[string]*anypb.Any,
requestHeadersToAdd []*corev3.HeaderValueOption, requestHeadersToRemove []string,
responseHeadersToAdd []*corev3.HeaderValueOption, responseHeadersToRemove []string) *routev3.Route {

route := &routev3.Route{
Name: routeName,
Match: match,
Action: action,
Metadata: metadata,
Decorator: decorator,
TypedPerFilterConfig: typedPerFilterConfig,
Expand All @@ -62,6 +61,12 @@ func generateRouteConfig(routeName string, match *routev3.RouteMatch, action *ro
ResponseHeadersToRemove: responseHeadersToRemove,
}

if redirectAction != nil {
route.Action = redirectAction
} else if action != nil {
route.Action = action
}

return route
}

Expand All @@ -76,7 +81,7 @@ func generateRouteMatch(routeRegex string) *routev3.RouteMatch {
return match
}

func generateRouteAction(apiType string, routeConfig *model.EndpointConfig, ratelimitCriteria *ratelimitCriteria) (action *routev3.Route_Route) {
func generateRouteAction(apiType string, routeConfig *model.EndpointConfig, ratelimitCriteria *ratelimitCriteria, mirrorClusterNames []string) (action *routev3.Route_Route) {
action = &routev3.Route_Route{
Route: &routev3.RouteAction{
HostRewriteSpecifier: &routev3.RouteAction_AutoHostRewrite{
Expand Down Expand Up @@ -108,9 +113,66 @@ func generateRouteAction(apiType string, routeConfig *model.EndpointConfig, rate
action.Route.RateLimits = generateRateLimitPolicy(ratelimitCriteria)
}

// Add request mirroring configurations
if mirrorClusterNames != nil && len(mirrorClusterNames) > 0 {
mirrorPolicies := []*routev3.RouteAction_RequestMirrorPolicy{}
for _, clusterName := range mirrorClusterNames {
mirrorPolicy := &routev3.RouteAction_RequestMirrorPolicy{
Cluster: clusterName,
}
mirrorPolicies = append(mirrorPolicies, mirrorPolicy)
}
action.Route.RequestMirrorPolicies = mirrorPolicies
}

return action
}

func generateRequestRedirectRoute(route string, policyParams interface{}) (action *routev3.Route_Redirect) {
policyParameters, _ := policyParams.(map[string]interface{})
scheme, _ := policyParameters[constants.RedirectScheme].(string)
hostname, _ := policyParameters[constants.RedirectHostname].(string)
port, _ := policyParameters[constants.RedirectPort].(int)
statusCode, _ := policyParameters[constants.RedirectStatusCode].(int)
replaceFullPath, _ := policyParameters[constants.RedirectPath].(string)
redirectActionStatusCode := mapStatusCodeToEnum(statusCode)
if redirectActionStatusCode == -1 {
_ = fmt.Errorf("Invalid status code provided")
}

action = &routev3.Route_Redirect{
Redirect: &routev3.RedirectAction{
SchemeRewriteSpecifier: &routev3.RedirectAction_HttpsRedirect{
HttpsRedirect: scheme == "https",
},
HostRedirect: hostname,
PortRedirect: uint32(port),
PathRewriteSpecifier: &routev3.RedirectAction_PathRedirect{
PathRedirect: replaceFullPath,
},
ResponseCode: routev3.RedirectAction_RedirectResponseCode(redirectActionStatusCode),
},
}
return action
}

func mapStatusCodeToEnum(statusCode int) int {
switch statusCode {
case 301:
return 0
case 302:
return 1
case 303:
return 2
case 307:
return 3
case 308:
return 4
default:
return -1
}
}

func generateRateLimitPolicy(ratelimitCriteria *ratelimitCriteria) []*routev3.RateLimit {

environmentValue := ratelimitCriteria.environment
Expand Down
Loading

0 comments on commit 8bfa83f

Please sign in to comment.