Skip to content

Commit

Permalink
Custom Transport Configuration support (#373)
Browse files Browse the repository at this point in the history
* Custom Transport Configuration support
---------

Co-authored-by: Darren Labey <[email protected]>
Co-authored-by: Armando Rodríguez <[email protected]>
  • Loading branch information
3 people authored Nov 10, 2023
1 parent 7d1170d commit 8f6ea46
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 69 deletions.
11 changes: 10 additions & 1 deletion src/main/java/com/checkout/AbstractCheckoutSdkBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public abstract class AbstractCheckoutSdkBuilder<T extends CheckoutApiClient> {
protected HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
private IEnvironment environment;
private Executor executor = ForkJoinPool.commonPool();
private TransportConfiguration transportConfiguration;

public AbstractCheckoutSdkBuilder<T> environment(final IEnvironment environment) {
this.environment = environment;
Expand All @@ -25,6 +26,11 @@ public AbstractCheckoutSdkBuilder<T> executor(final Executor executor) {
return this;
}

public AbstractCheckoutSdkBuilder<T> transportConfiguration(final TransportConfiguration transportConfiguration) {
this.transportConfiguration = transportConfiguration;
return this;
}

protected IEnvironment getEnvironment() {
return environment;
}
Expand All @@ -36,11 +42,14 @@ protected CheckoutConfiguration getCheckoutConfiguration() {
throw new CheckoutArgumentException("environment must be specified");
}
final SdkCredentials sdkCredentials = getSdkCredentials();
if (transportConfiguration == null) {
transportConfiguration = new DefaultTransportConfiguration();
}
return buildCheckoutConfiguration(sdkCredentials);
}

private CheckoutConfiguration buildCheckoutConfiguration(final SdkCredentials sdkCredentials) {
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), httpClientBuilder, executor);
return new DefaultCheckoutConfiguration(sdkCredentials, getEnvironment(), httpClientBuilder, executor, transportConfiguration);
}

public abstract T build();
Expand Down
51 changes: 27 additions & 24 deletions src/main/java/com/checkout/ApacheHttpClientTransport.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
package com.checkout;

import com.checkout.accounts.AccountsFileRequest;
import com.checkout.common.AbstractFileRequest;
import com.checkout.common.CheckoutUtils;
import com.checkout.common.FileRequest;
import lombok.extern.slf4j.Slf4j;
import static com.checkout.ClientOperation.POST;
import static com.checkout.common.CheckoutUtils.ACCEPT_JSON;
import static com.checkout.common.CheckoutUtils.PROJECT_NAME;
import static com.checkout.common.CheckoutUtils.getVersionFromManifest;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpHeaders.AUTHORIZATION;
import static org.apache.http.HttpHeaders.USER_AGENT;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
Expand All @@ -29,23 +42,12 @@
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import com.checkout.accounts.AccountsFileRequest;
import com.checkout.common.AbstractFileRequest;
import com.checkout.common.CheckoutUtils;
import com.checkout.common.FileRequest;

import static com.checkout.ClientOperation.POST;
import static com.checkout.common.CheckoutUtils.ACCEPT_JSON;
import static com.checkout.common.CheckoutUtils.PROJECT_NAME;
import static com.checkout.common.CheckoutUtils.getVersionFromManifest;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpHeaders.AUTHORIZATION;
import static org.apache.http.HttpHeaders.USER_AGENT;
import lombok.extern.slf4j.Slf4j;

@Slf4j
class ApacheHttpClientTransport implements Transport {
Expand All @@ -58,15 +60,16 @@ class ApacheHttpClientTransport implements Transport {
private final URI baseUri;
private final CloseableHttpClient httpClient;
private final Executor executor;
private final TransportConfiguration transportConfiguration;

ApacheHttpClientTransport(final URI baseUri, final HttpClientBuilder httpClientBuilder, final Executor executor) {
ApacheHttpClientTransport(final URI baseUri, final HttpClientBuilder httpClientBuilder, final Executor executor, final TransportConfiguration transportConfiguration) {
CheckoutUtils.validateParams("baseUri", baseUri, "httpClientBuilder", httpClientBuilder, "executor", executor);
this.baseUri = baseUri;
this.httpClient = httpClientBuilder
.setRedirectStrategy(new CustomAwsRedirectStrategy())
.build();
this.executor = executor;

this.transportConfiguration = transportConfiguration;
}

@Override
Expand Down Expand Up @@ -175,7 +178,7 @@ private Response performCall(final SdkAuthorization authorization,
} catch (final Exception e) {
log.error("Exception occurred during the execution of the client...", e);
}
return Response.builder().statusCode(HttpStatus.SC_BAD_REQUEST).build();
return Response.builder().statusCode(transportConfiguration.getDefaultHttpStatusCode()).build();
}

private Header[] sanitiseHeaders(final Header[] headers) {
Expand Down
25 changes: 13 additions & 12 deletions src/main/java/com/checkout/ApiClientImpl.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.checkout;

import com.checkout.common.AbstractFileRequest;
import com.checkout.common.CheckoutUtils;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils;
import static com.checkout.ClientOperation.DELETE;
import static com.checkout.ClientOperation.GET;
import static com.checkout.ClientOperation.PATCH;
import static com.checkout.ClientOperation.POST;
import static com.checkout.ClientOperation.PUT;
import static com.checkout.ClientOperation.QUERY;
import static com.checkout.common.CheckoutUtils.validateParams;

import java.io.ByteArrayInputStream;
import java.io.File;
Expand All @@ -16,13 +19,11 @@
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import static com.checkout.ClientOperation.DELETE;
import static com.checkout.ClientOperation.GET;
import static com.checkout.ClientOperation.PATCH;
import static com.checkout.ClientOperation.POST;
import static com.checkout.ClientOperation.PUT;
import static com.checkout.ClientOperation.QUERY;
import static com.checkout.common.CheckoutUtils.validateParams;
import org.apache.commons.lang3.StringUtils;

import com.checkout.common.AbstractFileRequest;
import com.checkout.common.CheckoutUtils;
import com.google.gson.reflect.TypeToken;

public class ApiClientImpl implements ApiClient {

Expand All @@ -33,7 +34,7 @@ public class ApiClientImpl implements ApiClient {

public ApiClientImpl(final CheckoutConfiguration configuration, final UriStrategy uriStrategy) {
this.serializer = new GsonSerializer();
this.transport = new ApacheHttpClientTransport(uriStrategy.getUri(), configuration.getHttpClientBuilder(), configuration.getExecutor());
this.transport = new ApacheHttpClientTransport(uriStrategy.getUri(), configuration.getHttpClientBuilder(), configuration.getExecutor(), configuration.getTransportConfiguration());
}

@Override
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/checkout/CheckoutConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.checkout;

import org.apache.http.impl.client.HttpClientBuilder;

import java.util.concurrent.Executor;

import org.apache.http.impl.client.HttpClientBuilder;

public interface CheckoutConfiguration {

IEnvironment getEnvironment();
Expand All @@ -14,4 +14,6 @@ public interface CheckoutConfiguration {

Executor getExecutor();

TransportConfiguration getTransportConfiguration();

}
16 changes: 16 additions & 0 deletions src/main/java/com/checkout/CustomTransportConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.checkout;

import lombok.Builder;
import lombok.Setter;

@Builder
public class CustomTransportConfiguration implements TransportConfiguration {

@Setter
private int defaultHttpStatusCode;

@Override
public int getDefaultHttpStatusCode() {
return defaultHttpStatusCode;
}
}
16 changes: 12 additions & 4 deletions src/main/java/com/checkout/DefaultCheckoutConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
package com.checkout;

import org.apache.http.impl.client.HttpClientBuilder;
import static com.checkout.common.CheckoutUtils.validateParams;

import java.util.concurrent.Executor;

import static com.checkout.common.CheckoutUtils.validateParams;
import org.apache.http.impl.client.HttpClientBuilder;

class DefaultCheckoutConfiguration implements CheckoutConfiguration {

private final SdkCredentials sdkCredentials;
private final HttpClientBuilder httpClientBuilder;
private final Executor executor;
private final IEnvironment environment;
private final TransportConfiguration transportConfiguration;

DefaultCheckoutConfiguration(final SdkCredentials sdkCredentials,
final IEnvironment environment,
final HttpClientBuilder httpClientBuilder,
final Executor executor) {
validateParams("sdkCredentials", sdkCredentials, "environment", environment, "httpClientBuilder", httpClientBuilder, "executor", executor);
final Executor executor,
final TransportConfiguration transportConfiguration) {
validateParams("sdkCredentials", sdkCredentials, "environment", environment, "httpClientBuilder", httpClientBuilder, "executor", executor, "transportConfiguration", transportConfiguration);
this.sdkCredentials = sdkCredentials;
this.httpClientBuilder = httpClientBuilder;
this.executor = executor;
this.environment = environment;
this.transportConfiguration = transportConfiguration;
}

@Override
Expand All @@ -43,4 +46,9 @@ public Executor getExecutor() {
public IEnvironment getEnvironment() {
return environment;
}

@Override
public TransportConfiguration getTransportConfiguration() {
return transportConfiguration;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/checkout/DefaultTransportConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.checkout;

import org.apache.http.HttpStatus;

public class DefaultTransportConfiguration implements TransportConfiguration {

private final int defaultHttpStatusCode;

public DefaultTransportConfiguration() {
this.defaultHttpStatusCode = HttpStatus.SC_BAD_REQUEST;
}

@Override
public int getDefaultHttpStatusCode() {
return defaultHttpStatusCode;
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/checkout/TransportConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.checkout;

public interface TransportConfiguration {

int getDefaultHttpStatusCode();
}
33 changes: 19 additions & 14 deletions src/test/java/com/checkout/DefaultCheckoutConfigurationTest.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
package com.checkout;

import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static java.net.URI.create;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;

import static java.net.URI.create;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import org.apache.http.HttpStatus;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

class DefaultCheckoutConfigurationTest {

private static final HttpClientBuilder DEFAULT_CLIENT_BUILDER = HttpClientBuilder.create();
private static final Executor DEFAULT_EXECUTOR = ForkJoinPool.commonPool();
private static final TransportConfiguration DEFAULT_TRANSPORT_CONFIGURATION = new DefaultTransportConfiguration();

@Test
void shouldFailCreatingConfiguration() {
try {
final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);
new DefaultCheckoutConfiguration(credentials, null, null, null);
new DefaultCheckoutConfiguration(credentials, null, null, null, null);
fail();
} catch (final Exception e) {
assertTrue(e instanceof CheckoutArgumentException);
Expand All @@ -37,7 +39,7 @@ void shouldCreateConfiguration() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR);
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals(Environment.PRODUCTION, configuration.getEnvironment());

}
Expand All @@ -47,7 +49,7 @@ void shouldCreateConfiguration_defaultHttpClientBuilderAndExecutor() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR);
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);

assertEquals(Environment.PRODUCTION, configuration.getEnvironment());
assertNotNull(configuration.getHttpClientBuilder());
Expand All @@ -61,8 +63,11 @@ void shouldCreateConfiguration_customHttpClientBuilderAndExecutor() {

final HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final TransportConfiguration transportConfiguration = CustomTransportConfiguration.builder()
.defaultHttpStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR)
.build();

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, httpClientBuilder, executorService);
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, httpClientBuilder, executorService, transportConfiguration);

assertEquals(Environment.PRODUCTION, configuration.getEnvironment());
assertEquals(httpClientBuilder, configuration.getHttpClientBuilder());
Expand All @@ -74,7 +79,7 @@ void shouldCreateConfigurationForProd() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR);
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, Environment.PRODUCTION, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals(Environment.PRODUCTION, configuration.getEnvironment());

}
Expand All @@ -92,7 +97,7 @@ void shouldCreateConfigurationWithCustomEnvironment() {

final StaticKeysSdkCredentials credentials = Mockito.mock(StaticKeysSdkCredentials.class);

final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, environment, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR);
final CheckoutConfiguration configuration = new DefaultCheckoutConfiguration(credentials, environment, DEFAULT_CLIENT_BUILDER, DEFAULT_EXECUTOR, DEFAULT_TRANSPORT_CONFIGURATION);
assertEquals(environment, configuration.getEnvironment());
assertEquals(environment.getCheckoutApi(), configuration.getEnvironment().getCheckoutApi());
assertEquals(environment.getOAuthAuthorizationApi(), configuration.getEnvironment().getOAuthAuthorizationApi());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.checkout;

import org.junit.jupiter.api.Test;

import static com.checkout.PlatformType.PREVIOUS;
import static com.checkout.TestHelper.INVALID_PREVIOUS_PK;
import static com.checkout.TestHelper.INVALID_PREVIOUS_SK;
Expand All @@ -12,6 +10,8 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import org.junit.jupiter.api.Test;

class PreviousStaticKeysSdkCredentialsTest {

@Test
Expand Down Expand Up @@ -64,15 +64,15 @@ void shouldFailToCreatePreviousStaticKeysSdkCredentialsForProd() {

try {
final PreviousStaticKeysSdkCredentials credentials = new PreviousStaticKeysSdkCredentials(VALID_PREVIOUS_SK, similarDefaultPk);
new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, null, null);
new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, null, null, null);
fail();
} catch (final Exception e) {
assertTrue(e instanceof CheckoutArgumentException);
assertEquals("invalid public key", e.getMessage());
}
try {
final PreviousStaticKeysSdkCredentials credentials = new PreviousStaticKeysSdkCredentials(similarDefaultSk, VALID_PREVIOUS_PK);
new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, null, null);
new DefaultCheckoutConfiguration(credentials, Environment.SANDBOX, null, null, null);
fail();
} catch (final Exception e) {
assertTrue(e instanceof CheckoutArgumentException);
Expand Down
Loading

0 comments on commit 8f6ea46

Please sign in to comment.