Skip to content

Commit

Permalink
Add tests for HTTPRoute filters
Browse files Browse the repository at this point in the history
  • Loading branch information
sgayangi committed Jul 2, 2024
1 parent 2aab03e commit ae8d511
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 47 deletions.
14 changes: 4 additions & 10 deletions adapter/internal/oasparser/envoyconf/routes_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func generateRouteAction(apiType string, routeConfig *model.EndpointConfig, rate
return action
}

func generateRequestRedirectRoute(route string, policyParams interface{}) (action *routev3.Route_Redirect) {
func generateRequestRedirectRoute(route string, policyParams interface{}) (*routev3.Route_Redirect, error) {
policyParameters, _ := policyParams.(map[string]interface{})
scheme, _ := policyParameters[constants.RedirectScheme].(string)
hostname, _ := policyParameters[constants.RedirectHostname].(string)
Expand All @@ -137,10 +137,10 @@ func generateRequestRedirectRoute(route string, policyParams interface{}) (actio
replaceFullPath, _ := policyParameters[constants.RedirectPath].(string)
redirectActionStatusCode := mapStatusCodeToEnum(statusCode)
if redirectActionStatusCode == -1 {
_ = fmt.Errorf("Invalid status code provided")
return nil, fmt.Errorf("Invalid status code provided")
}

action = &routev3.Route_Redirect{
action := &routev3.Route_Redirect{
Redirect: &routev3.RedirectAction{
SchemeRewriteSpecifier: &routev3.RedirectAction_HttpsRedirect{
HttpsRedirect: scheme == "https",
Expand All @@ -153,7 +153,7 @@ func generateRequestRedirectRoute(route string, policyParams interface{}) (actio
ResponseCode: routev3.RedirectAction_RedirectResponseCode(redirectActionStatusCode),
},
}
return action
return action, nil
}

func mapStatusCodeToEnum(statusCode int) int {
Expand All @@ -162,12 +162,6 @@ func mapStatusCodeToEnum(statusCode int) int {
return 0
case 302:
return 1
case 303:
return 2
case 307:
return 3
case 308:
return 4
default:
return -1
}
Expand Down
5 changes: 4 additions & 1 deletion adapter/internal/oasparser/envoyconf/routes_with_clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,10 @@ func createRoutes(params *routeCreateParams) (routes []*routev3.Route, err error
case constants.ActionRedirectRequest:
logger.LoggerOasparser.Debugf("Adding %s policy to request flow for %s %s",
constants.ActionRedirectRequest, resourcePath, operation.GetMethod())
requestRedirectAction = generateRequestRedirectRoute(resourcePath, requestPolicy.Parameters)
requestRedirectAction, err = generateRequestRedirectRoute(resourcePath, requestPolicy.Parameters)
if err != nil {
return nil, err
}
}
}

Expand Down
66 changes: 46 additions & 20 deletions runtime/config-deployer-service/ballerina/APIClient.bal
Original file line number Diff line number Diff line change
Expand Up @@ -860,30 +860,27 @@ public class APIClient {
model:HTTPHeader[] setHeaders = [];
string[] removeHeaders = [];
boolean hasRedirectPolicy = false;
model:HTTPRouteFilter headerModifierFilter = {'type: "RequestHeaderModifier"};
if !isRequest {
headerModifierFilter.'type = "ResponseHeaderModifier";
}

foreach APKOperationPolicy policy in operationPolicies {
if policy is HeaderModifierPolicy {
HeaderModifierPolicyParameters policyParameters = policy.parameters;
match policy.policyName {
AddHeaders => {
ModifierHeader[] headers = <ModifierHeader[]>policyParameters.headers;
foreach ModifierHeader header in headers {
headers.push(header);
addHeaders.push(header);
}
}
SetHeaders => {
ModifierHeader[] headers = <ModifierHeader[]>policyParameters.headers;
foreach ModifierHeader header in headers {
headers.push(header);
setHeaders.push(header);
}
}
RemoveHeaders => {
string[] headers = <string[]>policyParameters.headers;
foreach string header in headers {
headers.push(header);
removeHeaders.push(header);
}
}
}
Expand Down Expand Up @@ -939,35 +936,64 @@ public class APIClient {
}
RequestRedirectPolicyParameters policyParameters = policy.parameters;
string url = <string>policyParameters.url;
int statusCode = <int>policyParameters.statusCode;
model:HTTPRouteFilter redirectFilter = {'type: "RequestRedirect"};
int|error port = self.getPort(url);

if port is int {
redirectFilter.requestRedirect = {
hostname: self.getHost(url),
scheme: self.getProtocol(url),
statusCode: statusCode,
path: {
'type: "ReplaceFullPath",
replaceFullPath: self.getPath(url)
}
};
if policyParameters.statusCode is int {
int statusCode = <int>policyParameters.statusCode;
redirectFilter.requestRedirect.statusCode = statusCode;
}
}

httpRouteFilters.push(redirectFilter);
}
}
if isRequest {
model:HTTPHeaderFilter requestHeaderModifier = {};
if addHeaders != [] {
requestHeaderModifier.add = addHeaders;
}
if setHeaders != [] {
requestHeaderModifier.set = setHeaders;
}
if removeHeaders != [] {
requestHeaderModifier.remove = removeHeaders;
}

if addHeaders != [] {
headerModifierFilter.requestHeaderModifier.add = addHeaders;
}
if setHeaders != [] {
headerModifierFilter.requestHeaderModifier.set = setHeaders;
}
if removeHeaders != [] {
headerModifierFilter.requestHeaderModifier.remove = removeHeaders;
}
if addHeaders.length() > 0 || setHeaders.length() > 0 || removeHeaders.length() > 0 {
httpRouteFilters.push(headerModifierFilter);
if addHeaders.length() > 0 || setHeaders.length() > 0 || removeHeaders.length() > 0 {
model:HTTPRouteFilter headerModifierFilter = {
'type: "RequestHeaderModifier",
requestHeaderModifier: requestHeaderModifier
};
httpRouteFilters.push(headerModifierFilter);
}
} else {
model:HTTPHeaderFilter responseHeaderModifier = {};
if addHeaders != [] {
responseHeaderModifier.add = addHeaders;
}
if setHeaders != [] {
responseHeaderModifier.set = setHeaders;
}
if removeHeaders != [] {
responseHeaderModifier.remove = removeHeaders;
}
if addHeaders.length() > 0 || setHeaders.length() > 0 || removeHeaders.length() > 0 {
model:HTTPRouteFilter headerModifierFilter = {
'type: "ResponseHeaderModifier",
responseHeaderModifier: responseHeaderModifier
};
httpRouteFilters.push(headerModifierFilter);
}
}

return [httpRouteFilters, hasRedirectPolicy];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ components:
SetHeaders: "#/components/schemas/HeaderModifierPolicy"
RemoveHeaders: "#/components/schemas/HeaderModifierPolicy"
RequestMirror: "#/components/schemas/RequestMirrorPolicy"
RequstRedirect: "#/components/schemas/RequestRedirectPolicy"
RequestRedirect: "#/components/schemas/RequestRedirectPolicy"
BaseOperationPolicy:
title: API Operation Policy
required:
Expand Down Expand Up @@ -544,13 +544,10 @@ components:
statusCode:
type: integer
description: The status code to show upon redirecting the request.
default: 301
default: 302
enum:
- 301
- 302
- 303
- 307
- 308
additionalProperties: false
CustomClaims:
type: object
Expand Down
2 changes: 1 addition & 1 deletion runtime/config-deployer-service/ballerina/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public type RequestRedirectPolicy record {
# + statusCode - The status code to be sent as response to the client.
public type RequestRedirectPolicyParameters record {|
string url;
int statusCode;
int statusCode?;
|};

# Configuration for API deployment using the apk-conf file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,13 +768,10 @@
"statusCode": {
"type": "integer",
"description": "The status code to show upon redirecting the request.",
"default": 301,
"default": 302,
"enum": [
301,
302,
303,
307,
308
302
]
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import javax.net.ssl.TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
Expand Down Expand Up @@ -87,7 +88,11 @@ public SimpleHTTPClient() throws NoSuchAlgorithmException, KeyStoreException, Ke
.build();

final SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslcontext);
RequestConfig requestConfig = RequestConfig.custom()
.setRedirectsEnabled(false) // Disable redirects
.build();
this.client = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(csf)
.evictExpiredConnections()
.setMaxConnPerRoute(100)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
id: "api-with-request-and-response-filters"
id: "api-with-header-modifier-filters"
name: "EmployeeServiceAPI"
basePath: "/request-and-response-filters"
basePath: "/header-modifier-filters"
version: "3.14"
type: "REST"
defaultVersion: false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
id: "api-with-request-mirror-filter"
name: "EmployeeServiceAPI"
basePath: "/request-mirror-filter"
version: "3.14"
type: "REST"
defaultVersion: false
endpointConfigurations:
production:
endpoint: "http://backend:80/anything"
operations:
- target: "/employee"
verb: "GET"
secured: false
scopes: []
operationPolicies:
request:
- policyName: RequestMirror
policyVersion: v1
parameters:
urls:
- "http://backend:80/anything"
- "http://backend:80/anything"
- target: "/employee"
verb: "POST"
secured: true
scopes: []
- target: "/employee/{employeeId}"
verb: "PUT"
secured: true
scopes: []
- target: "/employee/{employeeId}"
verb: "DELETE"
secured: true
scopes: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
id: "api-with-request-redirect-filter"
name: "EmployeeServiceAPI"
basePath: "/request-redirect-filter"
version: "3.14"
type: "REST"
defaultVersion: false
endpointConfigurations:
production:
endpoint: "http://backend:80/anything"
operations:
- target: "/employee"
verb: "GET"
secured: false
scopes: []
operationPolicies:
request:
- policyName: RequestRedirect
policyVersion: v1
parameters:
url: "http://backend:80/anything"
statusCode: 301
- target: "/employee"
verb: "POST"
secured: true
scopes: []
- target: "/employee/{employeeId}"
verb: "PUT"
secured: true
scopes: []
- target: "/employee/{employeeId}"
verb: "DELETE"
secured: true
scopes: []
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ Feature: Test HTTPRoute Filter Header Modifier functionality
Scenario: Test request and response header modification functionality
Given The system is ready
And I have a valid subscription
When I use the APK Conf file "artifacts/apk-confs/request_and_response_filters.apk-conf"
When I use the APK Conf file "artifacts/apk-confs/header-modifier-filter.apk-conf"
And the definition file "artifacts/definitions/employees_api.json"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
And I send "GET" request to "https://default.gw.wso2.com:9095/request-and-response-filters/3.14/employee/" with body ""
And I send "GET" request to "https://default.gw.wso2.com:9095/header-modifier-filters/3.14/employee/" with body ""
And I eventually receive 200 response code, not accepting
| 401 |
And the response body should contain "\"Test-Request-Header\": \"Test-Value\""
Expand All @@ -22,7 +22,7 @@ Feature: Test HTTPRoute Filter Header Modifier functionality
Scenario: Undeploy the API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "api-with-request-and-response-filters"
When I undeploy the API whose ID is "api-with-header-modifier-filters"
Then the response status code should be 202


Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Feature: Test HTTPRoute Filter Request Mirror functionality
Scenario: Test request mirror functionality
Given The system is ready
And I have a valid subscription
When I use the APK Conf file "artifacts/apk-confs/request-mirror-filter.apk-conf"
And the definition file "artifacts/definitions/employees_api.json"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
And I send "GET" request to "https://default.gw.wso2.com:9095/request-mirror-filter/3.14/employee/" with body ""
And I eventually receive 200 response code, not accepting
| 401 |

Scenario: Undeploy the API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "api-with-request-mirror-filter"
Then the response status code should be 202


Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Feature: Test HTTPRoute Filter Request Redirect functionality
Scenario: Test request redirect functionality
Given The system is ready
And I have a valid subscription
When I use the APK Conf file "artifacts/apk-confs/request-redirect-filter.apk-conf"
And the definition file "artifacts/definitions/employees_api.json"
And make the API deployment request
Then the response status code should be 200
Then I set headers
| Authorization | bearer ${accessToken} |
And I send "GET" request to "https://default.gw.wso2.com:9095/request-redirect-filter/3.14/employee/" with body ""
And I eventually receive 301 response code, not accepting
| 401 |

Scenario: Undeploy the API
Given The system is ready
And I have a valid subscription
When I undeploy the API whose ID is "api-with-request-redirect-filter"
Then the response status code should be 202


0 comments on commit ae8d511

Please sign in to comment.