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 60ebc53ed Feat: Reuse same RemoteRepository to HTTP URI creation logic 
(#1878)
60ebc53ed is described below

commit 60ebc53ed202520beb165f9beb45eb755407a570
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu May 14 09:20:24 2026 +0200

    Feat: Reuse same RemoteRepository to HTTP URI creation logic (#1878)
    
    All HTTP remote repositories have pretty much same or similar expectations 
regarding base URI of a HTTP remote repository.
---
 .../aether/transport/apache/ApacheTransporter.java |   5 +-
 .../aether/transport/jdk/JdkTransporter.java       |  19 +---
 .../aether/transport/jetty/JettyTransporter.java   |  19 +---
 .../transport/http/HttpTransporterUtils.java       |  39 ++++++++
 .../transport/http/HttpTransporterUtilsTest.java   | 102 +++++++++++++++++++++
 5 files changed, 144 insertions(+), 40 deletions(-)

diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
index 637ca130c..6d6e6e01a 100644
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
+++ 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
@@ -160,10 +160,7 @@ final class ApacheTransporter extends AbstractTransporter 
implements HttpTranspo
         this.checksumExtractor = checksumExtractor;
         this.pathProcessor = pathProcessor;
         try {
-            this.baseUri = new URI(repository.getUrl()).parseServerAuthority();
-            if (baseUri.isOpaque()) {
-                throw new URISyntaxException(repository.getUrl(), "URL must 
not be opaque");
-            }
+            this.baseUri = HttpTransporterUtils.getBaseUri(repository);
             this.server = URIUtils.extractHost(baseUri);
             if (server == null) {
                 throw new URISyntaxException(repository.getUrl(), "URL lacks 
host name");
diff --git 
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk11/src/main/java/org/eclipse/aether/transport/jdk/JdkTransporter.java
 
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk11/src/main/java/org/eclipse/aether/transport/jdk/JdkTransporter.java
index 7dc032898..ef7924335 100644
--- 
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk11/src/main/java/org/eclipse/aether/transport/jdk/JdkTransporter.java
+++ 
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk11/src/main/java/org/eclipse/aether/transport/jdk/JdkTransporter.java
@@ -177,24 +177,7 @@ final class JdkTransporter extends AbstractTransporter 
implements HttpTransporte
         this.checksumExtractor = checksumExtractor;
         this.pathProcessor = pathProcessor;
         try {
-            URI uri = new URI(repository.getUrl()).parseServerAuthority();
-            if (uri.isOpaque()) {
-                throw new URISyntaxException(repository.getUrl(), "URL must 
not be opaque");
-            }
-            if (uri.getRawFragment() != null || uri.getRawQuery() != null) {
-                throw new URISyntaxException(repository.getUrl(), "URL must 
not have fragment or query");
-            }
-            String path = uri.getPath();
-            if (path == null) {
-                path = "/";
-            }
-            if (!path.startsWith("/")) {
-                path = "/" + path;
-            }
-            if (!path.endsWith("/")) {
-                path = path + "/";
-            }
-            this.baseUri = URI.create(uri.getScheme() + "://" + 
uri.getRawAuthority() + path);
+            this.baseUri = HttpTransporterUtils.getBaseUri(repository);
         } catch (URISyntaxException e) {
             throw new NoTransporterException(repository, e.getMessage(), e);
         }
diff --git 
a/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/JettyTransporter.java
 
b/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/JettyTransporter.java
index 57fe17855..56b6417f8 100644
--- 
a/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/JettyTransporter.java
+++ 
b/maven-resolver-transport-jetty/src/main/java/org/eclipse/aether/transport/jetty/JettyTransporter.java
@@ -128,24 +128,7 @@ final class JettyTransporter extends AbstractTransporter 
implements HttpTranspor
         this.checksumExtractor = checksumExtractor;
         this.pathProcessor = pathProcessor;
         try {
-            URI uri = new URI(repository.getUrl()).parseServerAuthority();
-            if (uri.isOpaque()) {
-                throw new URISyntaxException(repository.getUrl(), "URL must 
not be opaque");
-            }
-            if (uri.getRawFragment() != null || uri.getRawQuery() != null) {
-                throw new URISyntaxException(repository.getUrl(), "URL must 
not have fragment or query");
-            }
-            String path = uri.getPath();
-            if (path == null) {
-                path = "/";
-            }
-            if (!path.startsWith("/")) {
-                path = "/" + path;
-            }
-            if (!path.endsWith("/")) {
-                path = path + "/";
-            }
-            this.baseUri = URI.create(uri.getScheme() + "://" + 
uri.getRawAuthority() + path);
+            this.baseUri = HttpTransporterUtils.getBaseUri(repository);
         } catch (URISyntaxException e) {
             throw new NoTransporterException(repository, e.getMessage(), e);
         }
diff --git 
a/maven-resolver-util/src/main/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtils.java
 
b/maven-resolver-util/src/main/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtils.java
index 0a6f2797a..19adce116 100644
--- 
a/maven-resolver-util/src/main/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtils.java
+++ 
b/maven-resolver-util/src/main/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtils.java
@@ -19,6 +19,8 @@
 package org.eclipse.aether.util.connector.transport.http;
 
 import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.UnknownHostException;
 import java.nio.charset.Charset;
 import java.util.Collections;
@@ -299,4 +301,41 @@ public final class HttpTransporterUtils {
         }
         return Optional.empty();
     }
+
+    /**
+     * Shared code to create "base {@link URI}" for most common HTTP remote 
repositories and all HTTP transports.
+     * Note: this method just applies common validation and adjustments to 
URI, but it does not enforce protocol
+     * to be HTTP/HTTPS!
+     * <p>
+     * Validations and adjustments applied:
+     * <ul>
+     *     <li>URI string is parsed from {@link RemoteRepository#getUrl()} 
returned string</li>
+     *     <li>URI must have parsable {@link URI#parseServerAuthority()}</li>
+     *     <li>URI must not be opaque</li>
+     *     <li>URI must not have fragment or query</li>
+     *     <li>URI path is adjusted to end with {@code /} (slash).</li>
+     * </ul>
+     *
+     * @since 2.0.18
+     */
+    public static URI getBaseUri(RemoteRepository repository) throws 
URISyntaxException {
+        URI uri = new URI(repository.getUrl()).parseServerAuthority();
+        if (uri.isOpaque()) {
+            throw new URISyntaxException(repository.getUrl(), "URL must not be 
opaque");
+        }
+        if (uri.getRawFragment() != null || uri.getRawQuery() != null) {
+            throw new URISyntaxException(repository.getUrl(), "URL must not 
have fragment or query");
+        }
+        String path = uri.getRawPath();
+        if (path == null) {
+            path = "/";
+        }
+        if (!path.startsWith("/")) {
+            path = "/" + path;
+        }
+        if (!path.endsWith("/")) {
+            path = path + "/";
+        }
+        return new URI(uri.getScheme() + "://" + uri.getRawAuthority() + path);
+    }
 }
diff --git 
a/maven-resolver-util/src/test/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtilsTest.java
 
b/maven-resolver-util/src/test/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtilsTest.java
new file mode 100644
index 000000000..4d3f8455e
--- /dev/null
+++ 
b/maven-resolver-util/src/test/java/org/eclipse/aether/util/connector/transport/http/HttpTransporterUtilsTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.util.connector.transport.http;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.eclipse.aether.repository.RemoteRepository;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class HttpTransporterUtilsTest {
+    @Test
+    void goodUris() throws URISyntaxException {
+        URI uri;
+
+        // URI gets appended / (slash), if there is no trailing slash
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("as-is", "", 
"https://host.com/base/";).build());
+        assertEquals("https://host.com/base/";, uri.toASCIIString());
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("slash-append", "", 
"https://host.com/base";).build());
+        assertEquals("https://host.com/base/";, uri.toASCIIString());
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("root-append", "", 
"https://host.com";).build());
+        assertEquals("https://host.com/";, uri.toASCIIString());
+    }
+
+    @Test
+    void badUris() {
+        assertThrows(
+                URISyntaxException.class,
+                () -> HttpTransporterUtils.getBaseUri(new 
RemoteRepository.Builder("opaque", "", "is:opaque").build()));
+        assertThrows(
+                URISyntaxException.class,
+                () -> HttpTransporterUtils.getBaseUri(
+                        new RemoteRepository.Builder("query", "", 
"https://host.com/path?query";).build()));
+        assertThrows(
+                URISyntaxException.class,
+                () -> HttpTransporterUtils.getBaseUri(
+                        new RemoteRepository.Builder("fragment", "", 
"https://host.com/path#fragment";).build()));
+    }
+
+    @Test
+    void getBaseUriWithNonAscii() throws URISyntaxException {
+        URI uri;
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("repø", "default", 
"https://host.dk/repø";).build());
+        assertNotNull(uri);
+        assertEquals("https", uri.getScheme());
+        assertEquals("host.dk", uri.getHost());
+        assertEquals("/repø/", uri.getPath());
+        assertEquals("https://host.dk/rep%C3%B8/";, uri.toASCIIString());
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("repø", "default", 
"https://host.dk/rep%C3%B8";).build());
+        assertNotNull(uri);
+        assertEquals("https", uri.getScheme());
+        assertEquals("host.dk", uri.getHost());
+        assertEquals("/repø/", uri.getPath());
+        assertEquals("https://host.dk/rep%C3%B8/";, uri.toASCIIString());
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("räpo", "default", 
"https://host.de/räpo";).build());
+        assertNotNull(uri);
+        assertEquals("https", uri.getScheme());
+        assertEquals("host.de", uri.getHost());
+        assertEquals("/räpo/", uri.getPath());
+        assertEquals("https://host.de/r%C3%A4po/";, uri.toASCIIString());
+
+        uri = HttpTransporterUtils.getBaseUri(
+                new RemoteRepository.Builder("räpo", "default", 
"https://host.de/r%C3%A4po";).build());
+        assertNotNull(uri);
+        assertEquals("https", uri.getScheme());
+        assertEquals("host.de", uri.getHost());
+        assertEquals("/räpo/", uri.getPath());
+        assertEquals("https://host.de/r%C3%A4po/";, uri.toASCIIString());
+    }
+}

Reply via email to