Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/maven-verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
ff-site-run: false
maven4-enabled: true
verify-fail-fast: false
jdk-matrix: '[ "21", "25" ]'
jdk-matrix: '[ "21", "25", "26" ]'
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,39 @@ public final class ConfigurationProperties {
*/
public static final String HTTPS_SECURITY_MODE_INSECURE = "insecure";

public enum HttpVersion {
/**
* The default HTTP version supported by the respective transporter (the most recent stable one, usually HTTP/2)
*/
DEFAULT,
HTTP_1_1,
HTTP_2,
HTTP_3,
/**
* The maximum HTTP version supported by the respective transporter (may be unstable).
*/
MAXIMUM;
}

/**
* The maximum and preferred HTTP version. It transparently falls back to lower version if remote server does not support it.
* Value must be a {@link HttpVersion} enum value or its String representation. Default is {@link #DEFAULT_HTTP_VERSION}.
*
* @configurationSource {@link RepositorySystemSession#getConfigProperties()}
* @configurationType {@link ConfigurationProperties.HttpVersion}
* @configurationDefaultValue {@link #DEFAULT_HTTP_VERSION}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cstamas This constant cannot be extracted with

protected static Map<String, String> extractConstants(Path file) {
. Any idea how to fix this?

* @configurationRepoIdSuffix Yes
* @since NEXT
*/
public static final String HTTP_VERSION = PREFIX_TRANSPORT_HTTP + "version";

/**
* Default value if {@link #HTTP_VERSION} is not set.
*
* @since NEXT
*/
public static final HttpVersion DEFAULT_HTTP_VERSION = HttpVersion.DEFAULT;

/**
* A flag indicating which visitor should be used to "flatten" the dependency graph into list. In Maven 4
* the default is new "levelOrder", while Maven 3 used "preOrder". This property accepts values
Expand Down
25 changes: 24 additions & 1 deletion maven-resolver-demos/maven-resolver-demo-snippets/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
Expand Down Expand Up @@ -147,4 +146,28 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-bytecode-version</id>
<configuration>
<rules>
<enforceBytecodeVersion>
<excludes>
<!-- this requires Java 22 but is optional only -->
<exclude>org.eclipse.jetty.quic:jetty-quic-quiche-foreign</exclude>
</excludes>
</enforceBytecodeVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
13 changes: 13 additions & 0 deletions maven-resolver-test-http/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>jetty-http2-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http3</groupId>
<artifactId>jetty-http3-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.quic</groupId>
<artifactId>jetty-quic-quiche-server</artifactId>
</dependency>
<!-- no transitive dependency of jetty-quic-quiche-server, https://github.com/jetty/jetty.project/issues/15385 -->
<dependency>
<groupId>org.eclipse.jetty.quic</groupId>
<artifactId>jetty-quic-quiche-jna</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.compression</groupId>
<artifactId>jetty-compression-server</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,17 @@
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.pathmap.MatchedResource;
import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.http.pathmap.PathSpec;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
import org.eclipse.jetty.http3.server.HTTP3ServerConnectionFactory;
import org.eclipse.jetty.http3.server.HTTP3ServerQuicConfiguration;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.Content;
import org.eclipse.jetty.quic.quiche.server.QuicheServerConnector;
import org.eclipse.jetty.quic.quiche.server.QuicheServerQuicConfiguration;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
Expand All @@ -75,6 +80,7 @@
public class HttpServer {

public static class LogEntry {
private final HttpVersion version;

private final String method;

Expand All @@ -86,12 +92,17 @@ public static class LogEntry {

CountDownLatch responseHeadersAvailableSignal = new CountDownLatch(1);

public LogEntry(String method, String path, Map<String, String> requestHeaders) {
public LogEntry(HttpVersion version, String method, String path, Map<String, String> requestHeaders) {
this.version = version;
this.method = method;
this.path = path;
this.requestHeaders = requestHeaders;
}

public HttpVersion getVersion() {
return version;
}

public String getMethod() {
return method;
}
Expand Down Expand Up @@ -127,7 +138,7 @@ public void setResponseHeaders(Map<String, String> responseHeaders) {

@Override
public String toString() {
return method + " " + path;
return version + " " + method + " " + path;
}
}

Expand Down Expand Up @@ -160,6 +171,8 @@ public enum ChecksumHeader {

private ServerConnector httpsConnector;

private QuicheServerConnector http3Connector;

private String username;

private String password;
Expand Down Expand Up @@ -188,6 +201,10 @@ public int getHttpsPort() {
return httpsConnector != null ? httpsConnector.getLocalPort() : -1;
}

public int getHttp3Port() {
return http3Connector != null ? http3Connector.getLocalPort() : -1;
}

public String getHttpUrl() {
return "http://" + getHost() + ":" + getHttpPort();
}
Expand All @@ -196,37 +213,25 @@ public String getHttpsUrl() {
return "https://" + getHost() + ":" + getHttpsPort();
}

public HttpServer addSslConnector() {
return addSslConnector(true, true);
public String getHttp3Url() {
return "https://" + getHost() + ":" + getHttp3Port();
}

public HttpServer addSelfSignedSslConnector() {
return addSslConnector(false, true);
public HttpServer addHttp2ConnectorWithMutualTLS() {
return addHttp2Connector(true, true);
}

public HttpServer addSelfSignedSslConnectorHttp2Only() {
return addSslConnector(false, false);
public HttpServer addHttp2OnlyConnectorWithMutualTLS() {
return addHttp2Connector(false, true);
}

private HttpServer addSslConnector(boolean needClientAuth, boolean needHttp11) {
public HttpServer addHttp2OnlyConnector() {
return addHttp2Connector(false, false);
}

private HttpServer addHttp2Connector(boolean needClientAuth, boolean needHttp11) {
if (httpsConnector == null) {
SslContextFactory.Server ssl = new SslContextFactory.Server();
ssl.setNeedClientAuth(needClientAuth);
if (!needClientAuth) {
ssl.setKeyStorePath(HttpTransporterTest.KEY_STORE_SELF_SIGNED_PATH
.toAbsolutePath()
.toString());
ssl.setKeyStorePassword("server-pwd");
ssl.setSniRequired(false);
} else {
ssl.setKeyStorePath(
HttpTransporterTest.KEY_STORE_PATH.toAbsolutePath().toString());
ssl.setKeyStorePassword("server-pwd");
ssl.setTrustStorePath(
HttpTransporterTest.TRUST_STORE_PATH.toAbsolutePath().toString());
ssl.setTrustStorePassword("client-pwd");
ssl.setSniRequired(false);
}
SslContextFactory.Server ssl = createServerSslContextFactory(needClientAuth);

HttpConfiguration httpsConfig = new HttpConfiguration();
SecureRequestCustomizer customizer = new SecureRequestCustomizer();
Expand Down Expand Up @@ -259,6 +264,42 @@ private HttpServer addSslConnector(boolean needClientAuth, boolean needHttp11) {
return this;
}

private SslContextFactory.Server createServerSslContextFactory(boolean needClientAuth) {
SslContextFactory.Server ssl = new SslContextFactory.Server();
ssl.setSniRequired(false);
ssl.setKeyStorePath(
HttpTransporterTest.SERVER_STORE_PATH.toAbsolutePath().toString());
ssl.setKeyStorePassword("server-pwd");
ssl.setNeedClientAuth(needClientAuth);
if (needClientAuth) {
ssl.setTrustStorePath(
HttpTransporterTest.CLIENT_STORE_PATH.toAbsolutePath().toString());
ssl.setTrustStorePassword("client-pwd");
}
return ssl;
}

public HttpServer addHttp3Connector(boolean needClientAuth) {
if (http3Connector == null) {
QuicheServerQuicConfiguration serverQuicConfig = HTTP3ServerQuicConfiguration.configure(
new QuicheServerQuicConfiguration(HttpTransporterTest.PEM_QUICHE_SERVER_PATH));
http3Connector = new QuicheServerConnector(
server,
createServerSslContextFactory(needClientAuth),
serverQuicConfig,
new HTTP3ServerConnectionFactory());
// TODO: should share same port as https connector, so that the client can use the same port for both
// TCP/UDP
server.addConnector(http3Connector);
try {
http3Connector.start();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return this;
}

public List<LogEntry> getLogEntries() {
return logEntries;
}
Expand Down Expand Up @@ -322,6 +363,7 @@ public HttpServer start() throws Exception {

server = new Server();
httpConnector = new ServerConnector(server);
// always add the HTTP 1.1 connector
server.addConnector(httpConnector);

server.setHandler(new LogHandler(new CompressionEnforcingHandler(new Handler.Sequence(
Expand Down Expand Up @@ -484,14 +526,19 @@ private class LogHandler extends Handler.Wrapper {
public boolean handle(Request req, Response response, Callback callback) throws Exception {

LOGGER.info(
"{} {}{}",
"{} {} {}{}",
req.getConnectionMetaData().getHttpVersion(),
req.getMethod(),
req.getHttpURI().getDecodedPath(),
req.getHttpURI().getQuery() != null ? "?" + req.getHttpURI().getQuery() : "");

Map<String, String> requestHeaders =
toUnmodifiableMap(req.getHeaders()); // capture request headers before other handlers modify them
LogEntry logEntry = new LogEntry(req.getMethod(), req.getHttpURI().getPathQuery(), requestHeaders);
LogEntry logEntry = new LogEntry(
req.getConnectionMetaData().getHttpVersion(),
req.getMethod(),
req.getHttpURI().getPathQuery(),
requestHeaders);
logEntries.add(logEntry);
// prevent closing the response before logging (assume all writes are synchronous for simplicity)
boolean result = super.handle(req, response, callback);
Expand Down Expand Up @@ -602,6 +649,7 @@ public boolean handle(Request req, Response response, Callback callback) throws
Content.copy(req, Content.Sink.from(channel), fileWriteCallback);
fileWriteCallback.block();
} catch (IOException e) {
LOGGER.warn("Failed to write file {}", file.getAbsolutePath(), e);
file.delete();
throw e;
}
Expand Down
Loading
Loading