Skip to content

Commit d426f7b

Browse files
Thisara-WelmillaJalina2007
authored andcommitted
Improve x-wso2-api-version header resolving
1 parent 1baa2a3 commit d426f7b

File tree

5 files changed

+57
-81
lines changed

5 files changed

+57
-81
lines changed

components/action-mgt/org.wso2.carbon.identity.action.execution/src/main/java/org/wso2/carbon/identity/action/execution/internal/service/impl/ActionExecutorServiceImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@
7070
import org.wso2.carbon.identity.rule.evaluation.api.model.RuleEvaluationResult;
7171

7272
import java.util.ArrayList;
73+
import java.util.HashMap;
7374
import java.util.List;
75+
import java.util.Map;
7476
import java.util.concurrent.CompletableFuture;
7577
import java.util.concurrent.ExecutionException;
7678
import java.util.concurrent.ExecutorService;
@@ -88,6 +90,7 @@ public class ActionExecutorServiceImpl implements ActionExecutorService {
8890
private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
8991
private static final ActionExecutorServiceImpl INSTANCE = new ActionExecutorServiceImpl();
9092
private static final ActionExecutionDiagnosticLogger DIAGNOSTIC_LOGGER = new ActionExecutionDiagnosticLogger();
93+
private static final String API_VERSION_HEADER = "x-wso2-api-version";
9194
private final APIClient apiClient;
9295
private final ExecutorService executorService = ThreadLocalAwareExecutors.newFixedThreadPool(THREAD_POOL_SIZE);
9396

@@ -339,9 +342,11 @@ private ActionInvocationResponse executeActionAsynchronously(Action action,
339342
String payload) throws ActionExecutionException {
340343

341344
String apiEndpoint = action.getEndpoint().getUri();
345+
Map<String, String> headers = new HashMap<>();
346+
headers.put(API_VERSION_HEADER, action.getActionVersion());
342347
CompletableFuture<ActionInvocationResponse> actionExecutor = CompletableFuture.supplyAsync(
343348
() -> apiClient.callAPI(ActionType.valueOf(action.getType().getActionType()),
344-
apiEndpoint, authenticationMethod, payload), executorService);
349+
apiEndpoint, authenticationMethod, headers, payload), executorService);
345350
try {
346351
return actionExecutor.get();
347352
} catch (InterruptedException | ExecutionException e) {

components/action-mgt/org.wso2.carbon.identity.action.execution/src/main/java/org/wso2/carbon/identity/action/execution/internal/util/APIClient.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import java.io.IOException;
5050
import java.net.SocketTimeoutException;
5151
import java.nio.charset.StandardCharsets;
52+
import java.util.HashMap;
53+
import java.util.Map;
5254

5355
/**
5456
* This class is responsible for making API calls to the external services.
@@ -80,17 +82,27 @@ public APIClient() {
8082
.build();
8183
}
8284

85+
/**
86+
* Makes a POST API call to the given URL with the provided payload and headers.
87+
*
88+
* @param actionType Action type.
89+
* @param url URL of the API endpoint.
90+
* @param authMethod Authentication method to be used.
91+
* @param headers Headers to be included in the request.
92+
* @param payload Payload to be sent in the request body.
93+
* @return ActionInvocationResponse containing the response or error details.
94+
*/
8395
public ActionInvocationResponse callAPI(ActionType actionType, String url, AuthMethods.AuthMethod authMethod,
84-
String payload) {
96+
Map<String, String> headers, String payload) {
8597

8698
HttpPost httpPost = new HttpPost(url);
87-
setRequestEntity(httpPost, payload, authMethod, actionType);
99+
setRequestEntity(httpPost, payload, authMethod, headers);
88100

89101
return executeRequest(actionType, httpPost);
90102
}
91103

92104
private void setRequestEntity(HttpPost httpPost, String jsonRequest, AuthMethods.AuthMethod authMethod,
93-
ActionType actionType) {
105+
Map<String, String> headers) {
94106

95107
StringEntity entity = new StringEntity(jsonRequest, StandardCharsets.UTF_8);
96108
if (authMethod != null) {
@@ -99,8 +111,9 @@ private void setRequestEntity(HttpPost httpPost, String jsonRequest, AuthMethods
99111
httpPost.setEntity(entity);
100112
httpPost.setHeader("Accept", "application/json");
101113
httpPost.setHeader("Content-type", "application/json");
102-
httpPost.setHeader(ActionAPIVersionResolver.API_VERSION_HEADER,
103-
ActionAPIVersionResolver.resolveAPIVersion(actionType));
114+
for (Map.Entry<String, String> header : headers.entrySet()) {
115+
httpPost.setHeader(header.getKey(), header.getValue());
116+
}
104117
}
105118

106119
private ActionInvocationResponse executeRequest(ActionType actionType, HttpPost request) {

components/action-mgt/org.wso2.carbon.identity.action.execution/src/main/java/org/wso2/carbon/identity/action/execution/internal/util/ActionAPIVersionResolver.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

components/action-mgt/org.wso2.carbon.identity.action.execution/src/test/java/org/wso2/carbon/identity/action/execution/impl/ActionExecutorServiceImplTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -397,13 +397,13 @@ public void testBuildActionExecutionRequestWithExcludedHeaders()
397397
actionExecutionRequest);
398398

399399
ActionInvocationResponse actionInvocationResponse = createSuccessActionInvocationResponse();
400-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
400+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
401401

402402
actionExecutorService.execute(actionType, FlowContext.create(), "tenantDomain");
403403

404404
String payload = getJSONRequestPayload(actionExecutionRequest);
405405
// Verify that the HTTP client was called with the expected request
406-
verify(apiClient).callAPI(any(), any(), any(), eq(payload));
406+
verify(apiClient).callAPI(any(), any(), any(), any(), eq(payload));
407407
}
408408

409409
@Test
@@ -428,13 +428,13 @@ public void testBuildActionExecutionRequest() throws Exception {
428428
actionExecutionRequest);
429429

430430
ActionInvocationResponse actionInvocationResponse = createSuccessActionInvocationResponse();
431-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
431+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
432432

433433
actionExecutorService.execute(actionType, FlowContext.create(), "tenantDomain");
434434

435435
String payload = getJSONRequestPayload(actionExecutionRequest);
436436
// Verify that the HTTP client was called with the expected request
437-
verify(apiClient).callAPI(any(), any(), any(), eq(payload));
437+
verify(apiClient).callAPI(any(), any(), any(), any(), eq(payload));
438438
}
439439

440440
@Test
@@ -467,7 +467,7 @@ public void testActionExecuteSuccessWhenNoRuleConfiguredInAction() throws Except
467467

468468
ActionInvocationResponse actionInvocationResponse =
469469
createSuccessActionInvocationResponse();
470-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
470+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
471471

472472
ActionExecutionStatus expectedStatus = new SuccessStatus.Builder().build();
473473
when(actionExecutionResponseProcessor.getSupportedActionType()).thenReturn(actionType);
@@ -517,7 +517,7 @@ public void testActionExecuteSuccessWhenRuleConfiguredInActionIsSatisfied() thro
517517
actionExecutionRequest);
518518

519519
ActionInvocationResponse actionInvocationResponse = createSuccessActionInvocationResponse();
520-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
520+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
521521

522522
ActionExecutionStatus expectedStatus = new SuccessStatus.Builder().build();
523523
when(actionExecutionResponseProcessor.getSupportedActionType()).thenReturn(actionType);
@@ -557,7 +557,7 @@ public void testActionExecuteFailureWithRetiredActionVersion() throws Exception
557557

558558
ActionInvocationResponse actionInvocationResponse =
559559
createSuccessActionInvocationResponse();
560-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
560+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
561561

562562
ActionExecutionStatus expectedStatus = new SuccessStatus.Builder().build();
563563
when(actionExecutionResponseProcessor.getSupportedActionType()).thenReturn(actionType);
@@ -588,7 +588,7 @@ public void testActionExecuteFailure() throws Exception {
588588
mock(ActionExecutionRequest.class));
589589

590590
ActionInvocationResponse actionInvocationResponse = createFailureActionInvocationResponse();
591-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
591+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
592592

593593
ActionExecutionStatus expectedStatus = new FailedStatus(new Failure("Error_reason",
594594
"Error_description"));
@@ -627,7 +627,7 @@ public void testExecuteIncomplete() throws Exception {
627627
mock(ActionExecutionRequest.class));
628628

629629
ActionInvocationResponse actionInvocationResponse = createIncompleteActionInvocationResponse();
630-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
630+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
631631

632632
ActionExecutionStatus expectedStatus = new IncompleteStatus.Builder().build();
633633
when(actionExecutionResponseProcessor.getSupportedActionType()).thenReturn(actionType);
@@ -667,7 +667,7 @@ public void testActionExecuteFailureForUnexpectedAPIResponse() throws Exception
667667
mock(ActionExecutionRequest.class));
668668

669669
ActionInvocationResponse actionInvocationResponse = createActionInvocationResponseWithoutAPIResponse();
670-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
670+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
671671

672672
actionExecutorService.execute(actionType, FlowContext.create(), "tenantDomain");
673673
}
@@ -693,7 +693,7 @@ public void testExecuteError() throws Exception {
693693
mock(ActionExecutionRequest.class));
694694

695695
ActionInvocationResponse actionInvocationResponse = createErrorActionInvocationResponse();
696-
when(apiClient.callAPI(any(), any(), any(), any())).thenReturn(actionInvocationResponse);
696+
when(apiClient.callAPI(any(), any(), any(), any(), any())).thenReturn(actionInvocationResponse);
697697

698698
ActionExecutionStatus expectedStatus = new ErrorStatus(new Error("Error_message",
699699
"Error_description"));

components/action-mgt/org.wso2.carbon.identity.action.execution/src/test/java/org/wso2/carbon/identity/action/execution/util/APIClientTest.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.mockito.MockedStatic;
3535
import org.mockito.MockitoAnnotations;
3636
import org.testng.annotations.AfterMethod;
37+
import org.testng.annotations.BeforeClass;
3738
import org.testng.annotations.BeforeMethod;
3839
import org.testng.annotations.DataProvider;
3940
import org.testng.annotations.Test;
@@ -58,6 +59,7 @@
5859
import java.nio.charset.StandardCharsets;
5960
import java.util.Collections;
6061
import java.util.HashMap;
62+
import java.util.Map;
6163

6264
import static org.mockito.ArgumentMatchers.any;
6365
import static org.mockito.Mockito.mock;
@@ -84,10 +86,17 @@ public class APIClientTest {
8486

8587
private MockedStatic<ActionExecutorConfig> actionExecutorConfigStatic;
8688
private MockedStatic<LoggerUtils> loggerUtils;
89+
private final Map<String, String> headers = new HashMap<>();
8790

8891
@InjectMocks
8992
private APIClient apiClient;
9093

94+
@BeforeClass
95+
public void init() {
96+
97+
headers.put("x-wso2-api-version", "v1");
98+
}
99+
91100
@BeforeMethod
92101
public void setUp() throws Exception {
93102

@@ -122,7 +131,7 @@ public void testCallAPIUnacceptableContentTypeForSuccessResponse()
122131
when(httpResponse.getEntity()).thenReturn(entity);
123132

124133
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
125-
"http://example.com", null, "{}");
134+
"http://example.com", null, headers, "{}");
126135
assertNotNull(apiResponse);
127136
assertNull(apiResponse.getResponse());
128137
assertFalse(apiResponse.isRetry());
@@ -151,7 +160,7 @@ public void testCallAPIUnacceptablePayloadForSuccessResponse(String payload)
151160
when(httpResponse.getEntity()).thenReturn(entity);
152161

153162
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
154-
"http://example.com", null, "{}");
163+
"http://example.com", null, headers, "{}");
155164
assertNotNull(apiResponse);
156165
assertTrue(apiResponse.isError());
157166
assertFalse(apiResponse.isRetry());
@@ -178,7 +187,7 @@ public void testCallAPIAcceptablePayloadForSuccessResponse() throws Exception {
178187
when(httpResponse.getEntity()).thenReturn(entity);
179188

180189
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
181-
"http://example.com", null, "{}");
190+
"http://example.com", null, headers, "{}");
182191

183192
assertNotNull(apiResponse);
184193
assertNotNull(apiResponse.getResponse());
@@ -218,7 +227,7 @@ public void testCallAPIAcceptablePayloadForIncompleteResponse() throws Exception
218227
when(httpResponse.getEntity()).thenReturn(entity);
219228

220229
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
221-
"http://example.com", null, "{}");
230+
"http://example.com", null, headers, "{}");
222231

223232
assertNotNull(apiResponse);
224233
assertNotNull(apiResponse.getResponse());
@@ -258,7 +267,7 @@ public void testCallAPIUnexpectedIncompleteResponse(String incompleteResponse) t
258267
when(httpResponse.getEntity()).thenReturn(entity);
259268

260269
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
261-
"http://example.com", null, "{}");
270+
"http://example.com", null, headers, "{}");
262271

263272
assertNotNull(apiResponse);
264273
assertTrue(apiResponse.isError());
@@ -289,7 +298,7 @@ public void testCallAPIAcceptablePayloadForFailureResponse() throws Exception {
289298
.build();
290299
AuthMethods.AuthMethod bearAuth = new AuthMethods.BearerAuth(Collections.singletonList(authProperty));
291300
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
292-
"http://example.com", bearAuth, "{}");
301+
"http://example.com", bearAuth, headers, "{}");
293302

294303
assertNotNull(apiResponse);
295304
assertNotNull(apiResponse.getResponse());
@@ -334,7 +343,7 @@ public void testCallAPIUnexpectedFailureResponse(Object statusCode, Object conte
334343
when(httpResponse.getEntity()).thenReturn(entity);
335344

336345
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
337-
"http://example.com", null, "{}");
346+
"http://example.com", null, headers, "{}");
338347
assertNotNull(apiResponse);
339348
assertTrue(apiResponse.isError());
340349
assertFalse(apiResponse.isRetry());
@@ -385,7 +394,7 @@ public void testCallAPIUnexpectedErrorResponse(Object statusCode, Object content
385394
when(httpResponse.getEntity()).thenReturn(entity);
386395

387396
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
388-
"http://example.com", null, "{}");
397+
"http://example.com", null, headers, "{}");
389398
assertNotNull(apiResponse);
390399
assertTrue(apiResponse.isError());
391400
if ((int) statusCode == 500 || (int) statusCode == 502) { // This is a retry
@@ -430,7 +439,7 @@ public void testCallAPIAcceptablePayloadForErrorResponse(Object statusCode, Obje
430439
when(httpResponse.getEntity()).thenReturn(entity);
431440

432441
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
433-
"http://example.com", null, "{}");
442+
"http://example.com", null, headers, "{}");
434443

435444
assertNotNull(apiResponse);
436445
assertNotNull(apiResponse.getResponse());
@@ -466,7 +475,7 @@ public void testCallAPIRetryOnTimeoutAndReceiveSuccessResponse() throws Exceptio
466475
when(httpResponse.getEntity()).thenReturn(entity);
467476

468477
ActionInvocationResponse response = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
469-
"http://example.com", null, "{}");
478+
"http://example.com", null, headers, "{}");
470479

471480
assertNotNull(response);
472481
assertTrue(response.isSuccess());
@@ -491,7 +500,7 @@ public void testReceiveSuccessResponseWithExtendedResponseData() throws Exceptio
491500
when(httpResponse.getEntity()).thenReturn(entity);
492501

493502
ActionInvocationResponse response = apiClient.callAPI(ActionType.AUTHENTICATION,
494-
"http://example.com", null, "{}");
503+
"http://example.com", null, headers, "{}");
495504

496505
assertNotNull(response);
497506
assertTrue(response.isSuccess());
@@ -504,7 +513,7 @@ public void testCallAPIRetryOnTimeoutAndReachMaxRetryAttempts() throws Exception
504513
.thenThrow(new SocketTimeoutException("Read Timeout"));
505514

506515
ActionInvocationResponse response = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
507-
"http://example.com", null, "{}");
516+
"http://example.com", null, headers, "{}");
508517

509518
assertNotNull(response);
510519
assertTrue(response.isError());
@@ -518,7 +527,7 @@ public void testUnexpectedExceptionFromHttpClient() throws Exception {
518527
when(httpClient.execute(any(HttpPost.class))).thenThrow(new ClientProtocolException("Unexpected exception"));
519528

520529
ActionInvocationResponse apiResponse = apiClient.callAPI(ActionType.PRE_ISSUE_ACCESS_TOKEN,
521-
"http://example.com", null, "{}");
530+
"http://example.com", null, headers, "{}");
522531
assertNotNull(apiResponse);
523532
assertTrue(apiResponse.isError());
524533
assertEquals(apiResponse.getErrorLog(),

0 commit comments

Comments
 (0)