From 6ba652fa94255ec411f795fde9d0b261277d5a5d Mon Sep 17 00:00:00 2001 From: childish-sambino Date: Fri, 4 Feb 2022 10:00:28 -0600 Subject: [PATCH] [DI-1920] fix: set socket config with blocking operation timeout (#670) --- src/main/java/com/twilio/http/HttpClient.java | 38 ++++++----- .../com/twilio/http/NetworkHttpClient.java | 52 ++++++++------- .../com/twilio/http/ValidationClient.java | 63 +++++++++++++------ 3 files changed, 93 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/twilio/http/HttpClient.java b/src/main/java/com/twilio/http/HttpClient.java index 92fa2891c0..71e595ff34 100644 --- a/src/main/java/com/twilio/http/HttpClient.java +++ b/src/main/java/com/twilio/http/HttpClient.java @@ -1,24 +1,44 @@ package com.twilio.http; +import lombok.Getter; +import lombok.Setter; import org.apache.http.client.RedirectStrategy; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.SocketConfig; import org.apache.http.impl.client.DefaultRedirectStrategy; public abstract class HttpClient { + public static final int CONNECTION_TIMEOUT = 10000; + public static final int SOCKET_TIMEOUT = 30500; + public static final RequestConfig DEFAULT_REQUEST_CONFIG = RequestConfig + .custom() + .setConnectTimeout(CONNECTION_TIMEOUT) + .setSocketTimeout(SOCKET_TIMEOUT) + .build(); + public static final SocketConfig DEFAULT_SOCKET_CONFIG = SocketConfig + .custom() + .setSoTimeout(SOCKET_TIMEOUT) + .build(); + public static final int ANY_500 = -500; public static final int ANY_400 = -400; public static final int ANY_300 = -300; public static final int ANY_200 = -200; public static final int ANY_100 = -100; - public static final int[] RETRY_CODES = new int[]{ANY_500}; + public static final int[] RETRY_CODES = new int[] {ANY_500}; public static final int RETRIES = 3; public static final long DELAY_MILLIS = 100L; // Default redirect strategy to not auto-redirect for any methods (empty string array). + @Getter + @Setter private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(new String[0]); + @Getter private Response lastResponse; + @Getter private Request lastRequest; /** @@ -66,14 +86,6 @@ public Response reliableRequest(final Request request, final int[] retryCodes, i return response; } - public Response getLastResponse() { - return lastResponse; - } - - public Request getLastRequest() { - return lastRequest; - } - protected boolean shouldRetry(final Response response, final int[] retryCodes) { if (response == null) { return true; @@ -119,13 +131,5 @@ protected boolean shouldRetry(final Response response, final int[] retryCodes) { return false; } - public RedirectStrategy getRedirectStrategy() { - return redirectStrategy; - } - - public void setRedirectStrategy(final RedirectStrategy redirectStrategy) { - this.redirectStrategy = redirectStrategy; - } - public abstract Response makeRequest(final Request request); } diff --git a/src/main/java/com/twilio/http/NetworkHttpClient.java b/src/main/java/com/twilio/http/NetworkHttpClient.java index c7483476bd..ccee98d3ea 100644 --- a/src/main/java/com/twilio/http/NetworkHttpClient.java +++ b/src/main/java/com/twilio/http/NetworkHttpClient.java @@ -2,48 +2,54 @@ import com.twilio.Twilio; import com.twilio.exception.ApiException; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + import org.apache.http.HttpEntity; import org.apache.http.HttpHeaders; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; -import org.apache.http.client.utils.HttpClientUtils; -import org.apache.http.entity.BufferedHttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.HttpClientUtils; +import org.apache.http.config.SocketConfig; +import org.apache.http.entity.BufferedHttpEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; - public class NetworkHttpClient extends HttpClient { - private static final int CONNECTION_TIMEOUT = 10000; - private static final int SOCKET_TIMEOUT = 30500; - private final org.apache.http.client.HttpClient client; /** * Create a new HTTP Client. */ public NetworkHttpClient() { - this(RequestConfig.custom() - .setConnectTimeout(CONNECTION_TIMEOUT) - .setSocketTimeout(SOCKET_TIMEOUT) - .build() - ); + this(DEFAULT_REQUEST_CONFIG); } /** * Create a new HTTP Client with a custom request config. - * @param config a RequestConfig. + * + * @param requestConfig a RequestConfig. */ - public NetworkHttpClient(RequestConfig config) { + public NetworkHttpClient(final RequestConfig requestConfig) { + this(requestConfig, DEFAULT_SOCKET_CONFIG); + } + + /** + * Create a new HTTP Client with a custom request and socket config. + * + * @param requestConfig a RequestConfig. + * @param socketConfig a SocketConfig. + */ + public NetworkHttpClient(final RequestConfig requestConfig, final SocketConfig socketConfig) { Collection headers = Arrays.asList( new BasicHeader("X-Twilio-Client", "java-" + Twilio.VERSION), new BasicHeader(HttpHeaders.USER_AGENT, "twilio-java/" + Twilio.VERSION + " (" + Twilio.JAVA_VERSION + ")"), @@ -61,12 +67,13 @@ public NetworkHttpClient(RequestConfig config) { } PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); - connectionManager.setDefaultMaxPerRoute(10); - connectionManager.setMaxTotal(10*2); + connectionManager.setDefaultSocketConfig(socketConfig); + connectionManager.setDefaultMaxPerRoute(10); + connectionManager.setMaxTotal(10 * 2); client = clientBuilder .setConnectionManager(connectionManager) - .setDefaultRequestConfig(config) + .setDefaultRequestConfig(requestConfig) .setDefaultHeaders(headers) .setRedirectStrategy(this.getRedirectStrategy()) .build(); @@ -145,6 +152,5 @@ public Response makeRequest(final Request request) { HttpClientUtils.closeQuietly(response); } - } } diff --git a/src/main/java/com/twilio/http/ValidationClient.java b/src/main/java/com/twilio/http/ValidationClient.java index da3724cf36..64b5d90650 100644 --- a/src/main/java/com/twilio/http/ValidationClient.java +++ b/src/main/java/com/twilio/http/ValidationClient.java @@ -7,6 +7,7 @@ import org.apache.http.HttpVersion; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.config.SocketConfig; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; @@ -21,37 +22,56 @@ public class ValidationClient extends HttpClient { - private static final int CONNECTION_TIMEOUT = 10000; - private static final int SOCKET_TIMEOUT = 30500; - private static final RequestConfig DEFAULT_REQUEST_CONFIG = RequestConfig.custom() - .setConnectTimeout(CONNECTION_TIMEOUT) - .setSocketTimeout(SOCKET_TIMEOUT) - .build();; - private final org.apache.http.client.HttpClient client; /** * Create a new ValidationClient. * - * @param accountSid Twilio Account SID - * @param credentialSid Twilio Credential SID - * @param signingKey Twilio Signing key - * @param privateKey Private Key + * @param accountSid Twilio Account SID + * @param credentialSid Twilio Credential SID + * @param signingKey Twilio Signing key + * @param privateKey Private Key */ - public ValidationClient(String accountSid, String credentialSid, String signingKey, PrivateKey privateKey) { + public ValidationClient(final String accountSid, + final String credentialSid, + final String signingKey, + final PrivateKey privateKey) { this(accountSid, credentialSid, signingKey, privateKey, DEFAULT_REQUEST_CONFIG); } /** * Create a new ValidationClient. * - * @param accountSid Twilio Account SID - * @param credentialSid Twilio Credential SID - * @param signingKey Twilio Signing key - * @param privateKey Private Key - * @param config HTTP Request Config + * @param accountSid Twilio Account SID + * @param credentialSid Twilio Credential SID + * @param signingKey Twilio Signing key + * @param privateKey Private Key + * @param requestConfig HTTP Request Config + */ + public ValidationClient(final String accountSid, + final String credentialSid, + final String signingKey, + final PrivateKey privateKey, + final RequestConfig requestConfig) { + this(accountSid, credentialSid, signingKey, privateKey, requestConfig, DEFAULT_SOCKET_CONFIG); + } + + /** + * Create a new ValidationClient. + * + * @param accountSid Twilio Account SID + * @param credentialSid Twilio Credential SID + * @param signingKey Twilio Signing key + * @param privateKey Private Key + * @param requestConfig HTTP Request Config + * @param socketConfig HTTP Socket Config */ - public ValidationClient(String accountSid, String credentialSid, String signingKey, PrivateKey privateKey, RequestConfig config) { + public ValidationClient(final String accountSid, + final String credentialSid, + final String signingKey, + final PrivateKey privateKey, + final RequestConfig requestConfig, + final SocketConfig socketConfig) { Collection headers = Arrays.asList( new BasicHeader("X-Twilio-Client", "java-" + Twilio.VERSION), new BasicHeader(HttpHeaders.USER_AGENT, "twilio-java/" + Twilio.VERSION + " (" + Twilio.JAVA_VERSION + ")"), @@ -59,9 +79,12 @@ public ValidationClient(String accountSid, String credentialSid, String signingK new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "utf-8") ); + final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); + connectionManager.setDefaultSocketConfig(socketConfig); + client = HttpClientBuilder.create() - .setConnectionManager(new PoolingHttpClientConnectionManager()) - .setDefaultRequestConfig(config) + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(requestConfig) .setDefaultHeaders(headers) .setMaxConnPerRoute(10) .addInterceptorLast(new ValidationInterceptor(accountSid, credentialSid, signingKey, privateKey))