This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new 7dfd7898 [MRESOLVER-361] Unreliable TCP and retries (#288)
7dfd7898 is described below

commit 7dfd7898a54a84282ab59bb79c4e6c1feaecaf84
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Jun 1 09:17:36 2023 +0200

    [MRESOLVER-361] Unreliable TCP and retries (#288)
    
    Make httpClient retry for PUT.
    
    ---
    
    https://issues.apache.org/jira/browse/MRESOLVER-361
---
 .../aether/transport/http/HttpTransporter.java     | 35 ++++++++++++++++++----
 src/site/markdown/configuration.md                 |  2 ++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git 
a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
 
b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
index 471300a0..e788787f 100644
--- 
a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
+++ 
b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
@@ -45,6 +45,7 @@ import org.apache.http.HttpStatus;
 import org.apache.http.auth.AuthSchemeProvider;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.HttpResponseException;
 import org.apache.http.client.config.AuthSchemes;
 import org.apache.http.client.config.RequestConfig;
@@ -71,6 +72,7 @@ import org.apache.http.impl.auth.SPNegoSchemeFactory;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
 import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
 import org.apache.http.util.EntityUtils;
 import org.eclipse.aether.ConfigurationProperties;
 import org.eclipse.aether.RepositorySystemSession;
@@ -102,6 +104,15 @@ final class HttpTransporter extends AbstractTransporter {
 
     static final String USE_SYSTEM_PROPERTIES = 
"aether.connector.http.useSystemProperties";
 
+    static final String HTTP_RETRY_HANDLER_NAME = 
"aether.connector.http.retryHandler.name";
+
+    private static final String HTTP_RETRY_HANDLER_NAME_STANDARD = "standard";
+
+    private static final String HTTP_RETRY_HANDLER_NAME_DEFAULT = "default";
+
+    static final String HTTP_RETRY_HANDLER_REQUEST_SENT_ENABLED =
+            "aether.connector.http.retryHandler.requestSentEnabled";
+
     private static final Pattern CONTENT_RANGE_PATTERN =
             Pattern.compile("\\s*bytes\\s+([0-9]+)\\s*-\\s*([0-9]+)\\s*/.*");
 
@@ -214,11 +225,20 @@ final class HttpTransporter extends AbstractTransporter {
                 ConfigurationProperties.DEFAULT_HTTP_RETRY_HANDLER_COUNT,
                 ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT + "." + 
repository.getId(),
                 ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT);
+        String retryHandlerName = ConfigUtils.getString(
+                session,
+                HTTP_RETRY_HANDLER_NAME_STANDARD,
+                HTTP_RETRY_HANDLER_NAME + "." + repository.getId(),
+                HTTP_RETRY_HANDLER_NAME);
+        boolean retryHandlerRequestSentEnabled = ConfigUtils.getBoolean(
+                session,
+                false,
+                HTTP_RETRY_HANDLER_REQUEST_SENT_ENABLED + "." + 
repository.getId(),
+                HTTP_RETRY_HANDLER_REQUEST_SENT_ENABLED);
         String userAgent = ConfigUtils.getString(
                 session, ConfigurationProperties.DEFAULT_USER_AGENT, 
ConfigurationProperties.USER_AGENT);
 
         Charset credentialsCharset = Charset.forName(credentialEncoding);
-
         Registry<AuthSchemeProvider> authSchemeRegistry = 
RegistryBuilder.<AuthSchemeProvider>create()
                 .register(AuthSchemes.BASIC, new 
BasicSchemeFactory(credentialsCharset))
                 .register(AuthSchemes.DIGEST, new 
DigestSchemeFactory(credentialsCharset))
@@ -226,17 +246,23 @@ final class HttpTransporter extends AbstractTransporter {
                 .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
                 .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory())
                 .build();
-
         SocketConfig socketConfig =
                 SocketConfig.custom().setSoTimeout(requestTimeout).build();
-
         RequestConfig requestConfig = RequestConfig.custom()
                 .setConnectTimeout(connectTimeout)
                 .setConnectionRequestTimeout(connectTimeout)
                 .setSocketTimeout(requestTimeout)
                 .build();
 
-        DefaultHttpRequestRetryHandler retryHandler = new 
DefaultHttpRequestRetryHandler(retryCount, false);
+        HttpRequestRetryHandler retryHandler;
+        if (HTTP_RETRY_HANDLER_NAME_STANDARD.equals(retryHandlerName)) {
+            retryHandler = new StandardHttpRequestRetryHandler(retryCount, 
retryHandlerRequestSentEnabled);
+        } else if (HTTP_RETRY_HANDLER_NAME_DEFAULT.equals(retryHandlerName)) {
+            retryHandler = new DefaultHttpRequestRetryHandler(retryCount, 
retryHandlerRequestSentEnabled);
+        } else {
+            throw new IllegalArgumentException(
+                    "Unsupported parameter " + HTTP_RETRY_HANDLER_NAME + " 
value: " + retryHandlerName);
+        }
 
         HttpClientBuilder builder = HttpClientBuilder.create()
                 .setUserAgent(userAgent)
@@ -248,7 +274,6 @@ final class HttpTransporter extends AbstractTransporter {
                 .setConnectionManagerShared(true)
                 .setDefaultCredentialsProvider(toCredentialsProvider(server, 
repoAuthContext, proxy, proxyAuthContext))
                 .setProxy(proxy);
-
         final boolean useSystemProperties = ConfigUtils.getBoolean(
                 session, false, USE_SYSTEM_PROPERTIES + "." + 
repository.getId(), USE_SYSTEM_PROPERTIES);
         if (useSystemProperties) {
diff --git a/src/site/markdown/configuration.md 
b/src/site/markdown/configuration.md
index bba3b212..797e8433 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -42,6 +42,8 @@ Option | Type | Description | Default Value | Supports Repo 
ID Suffix
 `aether.connector.http.preemptiveAuth` | boolean | Should HTTP client use 
preemptive-authentication for all HTTP verbs (works only w/ BASIC). By default 
is disabled, as it is considered less secure. | `false` | yes
 `aether.connector.http.preemptivePutAuth` | boolean | Should HTTP client use 
preemptive-authentication for HTTP PUTs only (works only w/ BASIC). By default 
is enabled (same as Wagon). | `true` | yes
 `aether.connector.http.retryHandler.count` | int | The maximum number of times 
a request to a remote HTTP server should be retried in case of an error. | `3` 
| yes
+`aether.connector.http.retryHandler.name` | String | The name of retryHandler, 
supported values are "standard", that obeys RFC-2616, regarding idempotent 
methods, and "default" that considers requests w/o payload as idempotent. | 
`standard` | yes
+`aether.connector.http.retryHandler.requestSentEnabled` | boolean | Set to 
`true` if it is acceptable to retry non-idempotent requests, that have been 
sent. | `false` | yes
 `aether.connector.http.reuseConnections` | boolean | Should HTTP client reuse 
connections (in other words, pool connections) or not? | `true` | yes
 `aether.connector.http.supportWebDav` | boolean | If enabled, transport makes 
best effort to deploy to WebDAV server. This mode is not recommended, better 
use real Maven Repository Manager instead. | `false` | yes
 `aether.connector.http.useSystemProperties` | boolean | If enabled, underlying 
Apache HttpClient will use system properties as well to configure itself 
(typically used to set up HTTP Proxy via Java system properties). See <a 
href="https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html";>HttpClientBuilder</a>
 for used properties. This mode is **not recommended**, better use documented 
ways of configuration instead. |  [...]

Reply via email to