com.checkout.ApacheHttpClientTransport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checkout-sdk-java Show documentation
Show all versions of checkout-sdk-java Show documentation
Checkout SDK for Java https://checkout.com
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 org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
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 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;
@Slf4j
class ApacheHttpClientTransport implements Transport {
private static final String ACCEPT_CSV = "text/csv";
private static final String CKO_IDEMPOTENCY_KEY = "Cko-Idempotency-Key";
private static final String FILE = "file";
private static final String PURPOSE = "purpose";
private static final String PATH = "path";
private final URI baseUri;
private final CloseableHttpClient httpClient;
private final Executor executor;
ApacheHttpClientTransport(final URI baseUri, final HttpClientBuilder httpClientBuilder, final Executor executor) {
CheckoutUtils.validateParams("baseUri", baseUri, "httpClientBuilder", httpClientBuilder, "executor", executor);
this.baseUri = baseUri;
this.httpClient = httpClientBuilder
.setRedirectStrategy(new CustomAwsRedirectStrategy())
.build();
this.executor = executor;
}
@Override
public CompletableFuture invoke(final ClientOperation clientOperation,
final String path,
final SdkAuthorization authorization,
final String requestBody,
final String idempotencyKey,
final Map queryParams) {
return CompletableFuture.supplyAsync(() -> {
final HttpUriRequest request;
switch (clientOperation) {
case GET:
case GET_CSV_CONTENT:
request = new HttpGet(getRequestUrl(path));
break;
case PUT:
request = new HttpPut(getRequestUrl(path));
break;
case POST:
request = new HttpPost(getRequestUrl(path));
break;
case DELETE:
request = new HttpDelete(getRequestUrl(path));
break;
case PATCH:
request = new HttpPatch(getRequestUrl(path));
break;
case QUERY:
final List params = queryParams.entrySet().stream()
.map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
try {
request = new HttpGet(new URIBuilder(getRequestUrl(path)).addParameters(params).build());
} catch (final URISyntaxException e) {
throw new CheckoutException(e);
}
break;
default:
throw new UnsupportedOperationException("Unsupported HTTP Method: " + clientOperation);
}
if (idempotencyKey != null) {
request.setHeader(CKO_IDEMPOTENCY_KEY, idempotencyKey);
}
return performCall(authorization, requestBody, request, clientOperation);
}, executor);
}
@Override
public CompletableFuture submitFile(final String path, final SdkAuthorization authorization, final AbstractFileRequest fileRequest) {
return CompletableFuture.supplyAsync(() -> {
final HttpPost request = new HttpPost(getRequestUrl(path));
request.setEntity(getMultipartFileEntity(fileRequest));
return performCall(authorization, null, request, POST);
}, executor);
}
private HttpEntity getMultipartFileEntity(final AbstractFileRequest abstractFileRequest) {
final MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
if (abstractFileRequest instanceof FileRequest) {
final FileRequest fileRequest = (FileRequest) abstractFileRequest;
builder.addBinaryBody(FILE, fileRequest.getFile(), fileRequest.getContentType(), fileRequest.getFile().getName())
.addTextBody(PURPOSE, fileRequest.getPurpose().getPurpose(), ContentType.DEFAULT_BINARY)
.build();
} else if (abstractFileRequest instanceof AccountsFileRequest) {
final AccountsFileRequest fileRequest = (AccountsFileRequest) abstractFileRequest;
builder.addBinaryBody(PATH, fileRequest.getFile(), fileRequest.getContentType(), fileRequest.getFile().getName())
.addTextBody(PURPOSE, fileRequest.getPurpose().getPurpose(), ContentType.DEFAULT_TEXT)
.build();
} else {
throw new CheckoutException("Not supported request object");
}
return builder.build();
}
private Response performCall(final SdkAuthorization authorization,
final String requestBody,
final HttpUriRequest request,
final ClientOperation clientOperation) {
log.info("{}: {}", clientOperation, request.getURI());
request.setHeader(USER_AGENT, PROJECT_NAME + "/" + getVersionFromManifest());
request.setHeader(ACCEPT, getAcceptHeader(clientOperation));
request.setHeader(AUTHORIZATION, authorization.getAuthorizationHeader());
log.info("Request: " + Arrays.toString(sanitiseHeaders(request.getAllHeaders())));
if (requestBody != null && request instanceof HttpEntityEnclosingRequest) {
((HttpEntityEnclosingRequestBase) request).setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));
}
try (final CloseableHttpResponse response = httpClient.execute(request)) {
log.info("Response: " + response.getStatusLine().getStatusCode() + " " + Arrays.toString(response.getAllHeaders()));
final int statusCode = response.getStatusLine().getStatusCode();
final Map headers = Arrays.stream(response.getAllHeaders())
.collect(Collectors.toMap(Header::getName, Header::getValue));
if (statusCode != HttpStatus.SC_NOT_FOUND && response.getEntity() != null && response.getEntity().getContent() != null) {
return Response.builder()
.statusCode(statusCode)
.body(EntityUtils.toString(response.getEntity()))
.headers(headers)
.build();
}
return Response.builder().statusCode(statusCode).headers(headers).build();
} catch (final NoHttpResponseException e) {
log.error("Target server failed to respond with a valid HTTP response.");
return Response.builder().statusCode(HttpStatus.SC_GATEWAY_TIMEOUT).build();
} catch (final Exception e) {
log.error("Exception occurred during the execution of the client...", e);
}
return Response.builder().statusCode(HttpStatus.SC_BAD_REQUEST).build();
}
private Header[] sanitiseHeaders(final Header[] headers) {
return Arrays.stream(headers)
.filter(it -> !it.getName().equals(AUTHORIZATION))
.toArray(Header[]::new);
}
private String getAcceptHeader(final ClientOperation clientOperation) {
switch (clientOperation) {
case GET:
case PUT:
case POST:
case DELETE:
case PATCH:
case QUERY:
return ACCEPT_JSON;
case GET_CSV_CONTENT:
return ACCEPT_CSV;
default:
throw new IllegalStateException(String.format("Accept header not configured for client operation %s", clientOperation));
}
}
private String getRequestUrl(final String path) {
try {
return baseUri.resolve(path).toURL().toString();
} catch (final MalformedURLException e) {
throw new CheckoutException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy