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 15d05606 [MRESOLVER-315] Preemptive auth (#256)
15d05606 is described below

commit 15d056063a0e335c3cea3c77ef7b4877599c29fa
Author: Tamas Cservenak <[email protected]>
AuthorDate: Wed Mar 1 08:36:02 2023 +0100

    [MRESOLVER-315] Preemptive auth (#256)
    
    Add option for HTTP preemptive auth.
    
    ---
    
    https://issues.apache.org/jira/browse/MRESOLVER-315
---
 .../eclipse/aether/ConfigurationProperties.java    | 15 ++++++++++++
 .../aether/transport/http/HttpTransporter.java     | 11 +++++++++
 .../aether/transport/http/HttpTransporterTest.java | 28 ++++++++++++++++++++++
 src/site/markdown/configuration.md                 |  1 +
 4 files changed, 55 insertions(+)

diff --git 
a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
 
b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
index 7edecabe..5c9095ba 100644
--- 
a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
+++ 
b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
@@ -144,6 +144,21 @@ public final class ConfigurationProperties {
      */
     public static final int DEFAULT_HTTP_RETRY_HANDLER_COUNT = 3;
 
+    /**
+     * Should HTTP client use preemptive auth (w/ BASIC) or not?
+     *
+     * @see #DEFAULT_HTTP_PREEMPTIVE_AUTH
+     * @since 1.9.6
+     */
+    public static final String HTTP_PREEMPTIVE_AUTH = PREFIX_CONNECTOR + 
"http.preemptiveAuth";
+
+    /**
+     * The default value to use if {@link #HTTP_PREEMPTIVE_AUTH} isn't set 
(false).
+     *
+     * @since 1.9.6
+     */
+    public static final boolean DEFAULT_HTTP_PREEMPTIVE_AUTH = false;
+
     /**
      * A flag indicating whether checksums which are retrieved during checksum 
validation should be persisted in the
      * local filesystem next to the file they provide the checksum for.
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 300f5b31..59bbfc07 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
@@ -61,6 +61,7 @@ import org.apache.http.config.RegistryBuilder;
 import org.apache.http.config.SocketConfig;
 import org.apache.http.entity.AbstractHttpEntity;
 import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.auth.BasicScheme;
 import org.apache.http.impl.auth.BasicSchemeFactory;
 import org.apache.http.impl.auth.DigestSchemeFactory;
 import org.apache.http.impl.auth.KerberosSchemeFactory;
@@ -117,6 +118,8 @@ final class HttpTransporter extends AbstractTransporter {
 
     private final LocalState state;
 
+    private final boolean preemptiveAuth;
+
     HttpTransporter(
             Map<String, ChecksumExtractor> checksumExtractors,
             RemoteRepository repository,
@@ -151,6 +154,11 @@ final class HttpTransporter extends AbstractTransporter {
                 ConfigurationProperties.HTTP_HEADERS + "." + 
repository.getId(),
                 ConfigurationProperties.HTTP_HEADERS);
 
+        this.preemptiveAuth = ConfigUtils.getBoolean(
+                session,
+                ConfigurationProperties.DEFAULT_HTTP_PREEMPTIVE_AUTH,
+                ConfigurationProperties.HTTP_PREEMPTIVE_AUTH + "." + 
repository.getId(),
+                ConfigurationProperties.HTTP_PREEMPTIVE_AUTH);
         String credentialEncoding = ConfigUtils.getString(
                 session,
                 ConfigurationProperties.DEFAULT_HTTP_CREDENTIAL_ENCODING,
@@ -348,6 +356,9 @@ final class HttpTransporter extends AbstractTransporter {
     }
 
     private void prepare(HttpUriRequest request, SharingHttpContext context) {
+        if (preemptiveAuth) {
+            state.setAuthScheme(server, new BasicScheme());
+        }
         boolean put = 
HttpPut.METHOD_NAME.equalsIgnoreCase(request.getMethod());
         if (state.getWebDav() == null && (put || isPayloadPresent(request))) {
             HttpOptions req = commonHeaders(new HttpOptions(request.getURI()));
diff --git 
a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
 
b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
index a6557ed7..db00dc66 100644
--- 
a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
+++ 
b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
@@ -1036,6 +1036,34 @@ public class HttpTransporterTest {
         
assertNotNull(httpServer.getLogEntries().get(0).headers.get("Proxy-Authorization"));
     }
 
+    @Test
+    public void testAuthSchemePreemptive() throws Exception {
+        httpServer.setAuthentication("testuser", "testpass");
+        session.setCache(new DefaultRepositoryCache());
+        auth = new AuthenticationBuilder()
+                .addUsername("testuser")
+                .addPassword("testpass")
+                .build();
+
+        
session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, false);
+        newTransporter(httpServer.getHttpUrl());
+        GetTask task = new GetTask(URI.create("repo/file.txt"));
+        transporter.get(task);
+        assertEquals("test", task.getDataString());
+        // there ARE challenge round-trips
+        assertEquals(2, httpServer.getLogEntries().size());
+
+        httpServer.getLogEntries().clear();
+
+        
session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, true);
+        newTransporter(httpServer.getHttpUrl());
+        task = new GetTask(URI.create("repo/file.txt"));
+        transporter.get(task);
+        assertEquals("test", task.getDataString());
+        // there are NO challenge round-trips, all goes through at first
+        assertEquals(1, httpServer.getLogEntries().size());
+    }
+
     @Test
     public void testConnectionReuse() throws Exception {
         httpServer.addSslConnector();
diff --git a/src/site/markdown/configuration.md 
b/src/site/markdown/configuration.md
index c752e290..649cc3c9 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -37,6 +37,7 @@ Option | Type | Description | Default Value | Supports Repo 
ID Suffix
 `aether.connector.http.cacheState` | boolean | Flag indicating whether a 
memory-based cache is used for user tokens, connection managers, expect 
continue requests and authentication schemes. | `true` | no
 `aether.connector.http.credentialEncoding` | String | The encoding/charset to 
use when exchanging credentials with HTTP servers. | `"ISO-8859-1"` | yes
 `aether.connector.http.headers` | `Map<String, String>` | The request headers 
to use for HTTP-based repository connectors. The headers are specified using a 
map of strings mapping a header name to its value. The repository-specific 
headers map is supposed to be complete, i.e. is not merged with the general 
headers map. | - | yes
+`aether.connector.http.preemptiveAuth` | boolean | Should HTTP client use 
preemptive-authentication (works only w/ BASIC) or not. | `false` | 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.https.cipherSuites` | String | Comma-separated list of 
[Cipher 
Suites](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#ciphersuites)
 which are enabled for HTTPS connections. | - (no restriction) | no
 `aether.connector.https.protocols` | String | Comma-separated list of 
[Protocols](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#jssenames)
 which are enabled for HTTPS connections. | - (no restriction) | no

Reply via email to