Skip to content

Commit 99101ee

Browse files
authored
Implement configurable HTTP timeouts with detailed error handling (#1078)
* Implement configurable HTTP timeouts with detailed error handling This PR enhances the HTTP client implementation by: - Adding support for different types of timeout configuration via environment variables - Implementing specific error handling for three distinct timeout scenarios (socket, connect, connection request) - Adding proper error codes to identify the exact type of timeout that occurred - Improving diagnostics through detailed error reporting These changes allow applications to better understand connection failures and configure timeout behavior according to their specific requirements. Issue: 207597 * Fix errorCode var name.
1 parent d9cd101 commit 99101ee

2 files changed

Lines changed: 53 additions & 12 deletions

File tree

common/src/main/java/com/genexus/internet/GXHttpClient.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,11 @@ private byte[] addToArray(byte[] in, byte[] val)
720720
}
721721

722722
protected void setExceptionsCatch(Exception e) {
723-
setErrCode(ERROR_IO);
723+
setExceptionsCatch(ERROR_IO, e);
724+
}
725+
726+
protected void setExceptionsCatch(int errorCode, Exception e) {
727+
setErrCode(errorCode);
724728
setErrDescription(e.getMessage());
725729
}
726730

java/src/main/java/com/genexus/internet/HttpClientJavaLib.java

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.genexus.internet;
22

33
import java.io.*;
4-
import java.net.InetAddress;
5-
import java.net.URISyntaxException;
6-
import java.net.UnknownHostException;
4+
import java.net.*;
75
import java.nio.charset.Charset;
86
import java.nio.charset.StandardCharsets;
97
import java.security.KeyManagementException;
@@ -12,12 +10,14 @@
1210
import java.security.UnrecoverableKeyException;
1311
import java.security.cert.CertificateException;
1412
import java.util.*;
15-
import java.net.URI;
1613
import javax.net.ssl.SSLContext;
1714

1815
import org.apache.http.*;
1916
import org.apache.http.HttpResponse;
17+
import org.apache.http.client.CookieStore;
2018
import org.apache.http.client.config.CookieSpecs;
19+
import org.apache.http.conn.ConnectTimeoutException;
20+
import org.apache.http.conn.ConnectionPoolTimeoutException;
2121
import org.apache.http.conn.DnsResolver;
2222
import org.apache.http.conn.routing.HttpRoute;
2323
import org.apache.http.conn.ssl.NoopHostnameVerifier;
@@ -65,6 +65,9 @@
6565
import com.genexus.specific.java.*;
6666

6767
public class HttpClientJavaLib extends GXHttpClient {
68+
private static final int ERROR_SOCKET_TIMEOUT = 1001;
69+
private static final int ERROR_CONNECT_TIMEOUT = 1002;
70+
private static final int ERROR_CONNECTION_REQUEST_TIMEOUT = 1003;
6871

6972
private static final DnsResolver FIRST_IP_DNS_RESOLVER = host -> {
7073
InetAddress[] allIps = SystemDefaultDnsResolver.INSTANCE.resolve(host);
@@ -417,11 +420,35 @@ public void execute(String method, String url) {
417420

418421
int msTimeout = getTimeout() * 1000;
419422

423+
int connectTimeout = msTimeout;
424+
int connectionRequestTimeout = msTimeout;
425+
int socketTimeout = msTimeout;
426+
427+
try {
428+
String connectTimeoutEnv = System.getenv("HTTP_CONNECT_TIMEOUT_MS");
429+
if (connectTimeoutEnv != null && !connectTimeoutEnv.trim().isEmpty()) {
430+
connectTimeout = Integer.parseInt(connectTimeoutEnv);
431+
}
432+
433+
String connectionRequestTimeoutEnv = System.getenv("HTTP_CONNECTION_REQUEST_TIMEOUT_MS");
434+
if (connectionRequestTimeoutEnv != null && !connectionRequestTimeoutEnv.trim().isEmpty()) {
435+
connectionRequestTimeout = Integer.parseInt(connectionRequestTimeoutEnv);
436+
}
437+
438+
String socketTimeoutEnv = System.getenv("HTTP_SOCKET_TIMEOUT_MS");
439+
if (socketTimeoutEnv != null && !socketTimeoutEnv.trim().isEmpty()) {
440+
socketTimeout = Integer.parseInt(socketTimeoutEnv);
441+
}
442+
}
443+
catch (NumberFormatException e) {
444+
logger.error("Error parsing timeout environment variables", e);
445+
}
446+
420447
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
421448
.setCookieSpec(CookieSpecs.STANDARD)
422-
.setSocketTimeout(msTimeout)
423-
.setConnectionRequestTimeout(msTimeout)
424-
.setConnectTimeout(msTimeout);
449+
.setSocketTimeout(socketTimeout)
450+
.setConnectionRequestTimeout(connectionRequestTimeout)
451+
.setConnectTimeout(connectTimeout);
425452

426453
this.httpClientBuilder.setRoutePlanner(null);
427454

@@ -650,11 +677,14 @@ public void execute(String method, String url) {
650677
if (response.containsHeader("Transfer-Encoding")) {
651678
isChunkedResponse = response.getFirstHeader("Transfer-Encoding").getValue().equalsIgnoreCase("chunked");
652679
}
653-
680+
} catch (ConnectionPoolTimeoutException e) {
681+
setExecuteExceptionsCatch(ERROR_CONNECTION_REQUEST_TIMEOUT, e);
682+
} catch (ConnectTimeoutException e) {
683+
setExecuteExceptionsCatch(ERROR_CONNECT_TIMEOUT, e);
684+
} catch (SocketTimeoutException e) {
685+
setExecuteExceptionsCatch(ERROR_SOCKET_TIMEOUT, e);
654686
} catch (IOException e) {
655-
setExceptionsCatch(e);
656-
this.statusCode = 0;
657-
this.reasonLine = "";
687+
setExecuteExceptionsCatch(ERROR_IO, e);
658688
}
659689
finally {
660690
if (Application.isJMXEnabled()){
@@ -671,6 +701,13 @@ public void execute(String method, String url) {
671701
}
672702
}
673703

704+
private void setExecuteExceptionsCatch(int errorCode, Exception e) {
705+
setExceptionsCatch(errorCode, e);
706+
this.statusCode = 0;
707+
this.reasonLine = "";
708+
logger.error("Execute error: " + e.getMessage(), e);
709+
}
710+
674711
private synchronized void displayHTTPConnections(){
675712
Iterator<HttpRoute> iterator = storedRoutes.iterator();
676713
while (iterator.hasNext()) {

0 commit comments

Comments
 (0)