From 14ecf2728942c0868c18bd28fbf69d8b64b6cca0 Mon Sep 17 00:00:00 2001 From: arimu1 <19286898+arimu1@users.noreply.github.com> Date: Fri, 28 Aug 2026 13:24:50 +0700 Subject: [PATCH] fix: honor NetworkHttpClient RequestConfig in makeRequest --- .../com/twilio/http/NetworkHttpClient.java | 8 +++- .../twilio/http/NetworkHttpClientTest.java | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/twilio/http/NetworkHttpClient.java b/src/main/java/com/twilio/http/NetworkHttpClient.java index 0d40e4cb8c..2a3e3c0e23 100644 --- a/src/main/java/com/twilio/http/NetworkHttpClient.java +++ b/src/main/java/com/twilio/http/NetworkHttpClient.java @@ -45,6 +45,8 @@ public class NetworkHttpClient extends HttpClient { protected final CloseableHttpClient client; + private final RequestConfig requestConfig; + private boolean isCustomClient; /** @@ -70,6 +72,7 @@ public NetworkHttpClient(final RequestConfig requestConfig) { * @param socketConfig a SocketConfig. */ public NetworkHttpClient(final RequestConfig requestConfig, final SocketConfig socketConfig) { + this.requestConfig = requestConfig; Collection headers = Arrays.asList( new BasicHeader("X-Twilio-Client", "java-" + Twilio.VERSION), // The Accept header is intentionally omitted to support both SCIM and JSON content types. @@ -109,6 +112,7 @@ public NetworkHttpClient(final RequestConfig requestConfig, final SocketConfig s * @param clientBuilder an HttpClientBuilder. */ public NetworkHttpClient(HttpClientBuilder clientBuilder) { + this.requestConfig = DEFAULT_REQUEST_CONFIG; Collection headers = Arrays.asList( new BasicHeader("X-Twilio-Client", "java-" + Twilio.VERSION), new BasicHeader(HttpHeaders.ACCEPT, "application/json"), @@ -133,7 +137,9 @@ public Response makeRequest(final Request request) { HttpMethod method = request.getMethod(); HttpUriRequestBase httpUriRequestBase = createHttpUriRequestBase(request); - httpUriRequestBase.setConfig(DEFAULT_REQUEST_CONFIG); + if (!isCustomClient) { + httpUriRequestBase.setConfig(this.requestConfig); + } httpUriRequestBase.setVersion(HttpVersion.HTTP_1_1); diff --git a/src/test/java/com/twilio/http/NetworkHttpClientTest.java b/src/test/java/com/twilio/http/NetworkHttpClientTest.java index 21c457c921..38b6170998 100644 --- a/src/test/java/com/twilio/http/NetworkHttpClientTest.java +++ b/src/test/java/com/twilio/http/NetworkHttpClientTest.java @@ -4,8 +4,11 @@ import com.twilio.exception.ApiConnectionException; import com.twilio.http.IRequest.FormParameters; import com.twilio.http.IRequest.FormParameters.Type; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.util.Timeout; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; @@ -16,6 +19,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.ArgumentCaptor; + +import java.lang.reflect.Field; import java.io.ByteArrayInputStream; import java.io.File; @@ -374,4 +380,45 @@ public void testRequestWithMultipleHeaders() throws IOException { } + @Test + public void testMakeRequestUsesConstructorRequestConfig() throws Exception { + RequestConfig customConfig = RequestConfig.custom() + .setResponseTimeout(Timeout.ofMilliseconds(12345)) + .build(); + + CloseableHttpClient injectedClient = mock(CloseableHttpClient.class); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpUriRequestBase.class); + when(injectedClient.execute(requestCaptor.capture())).thenReturn(mockResponse); + when(mockEntity.isRepeatable()).thenReturn(true); + when(mockEntity.getContentLength()).thenReturn(1L); + when(mockEntity.getContent()).thenReturn(new ByteArrayInputStream("ok".getBytes("UTF-8"))); + when(mockResponse.getEntity()).thenReturn(mockEntity); + when(mockResponse.getCode()).thenReturn(200); + + NetworkHttpClient clientWithConfig = new NetworkHttpClient(customConfig); + Field clientField = NetworkHttpClient.class.getDeclaredField("client"); + clientField.setAccessible(true); + clientField.set(clientWithConfig, injectedClient); + + when(mockRequest.getMethod()).thenReturn(HttpMethod.GET); + when(mockRequest.constructURL()).thenReturn(new URL("http://foo.com/hello")); + when(mockRequest.requiresAuthentication()).thenReturn(false); + when(mockRequest.getHeaderParams()).thenReturn(new HashMap<>()); + + clientWithConfig.makeRequest(mockRequest); + + assertEquals(customConfig, requestCaptor.getValue().getConfig()); + } + + @Test + public void testCustomHttpClientBuilderDoesNotSetPerRequestConfig() throws IOException { + setup(200, "frobozz", HttpMethod.GET, false); + + client.makeRequest(mockRequest); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpUriRequestBase.class); + verify(mockClient).execute(requestCaptor.capture()); + assertNull(requestCaptor.getValue().getConfig()); + } + }