Skip to content

Commit 45fa673

Browse files
committed
HTTP/3 impl
1 parent 950e7e8 commit 45fa673

28 files changed

+1960
-93
lines changed

vertx-core/src/main/java/io/vertx/core/Vertx.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,22 @@ default NetClient createNetClient() {
229229
*/
230230
HttpServer createHttpServer(HttpServerOptions options);
231231

232+
/**
233+
* Create an HTTP3 client using the specified options
234+
*
235+
* @param options the options to use
236+
* @return the server
237+
*/
238+
HttpClientAgent createHttpClient(Http3ClientOptions options);
239+
240+
/**
241+
* Create an HTTP3 server using the specified options
242+
*
243+
* @param options the options to use
244+
* @return the server
245+
*/
246+
HttpServer createHttpServer(Http3ServerOptions options);
247+
232248
/**
233249
* Create an HTTP/HTTPS server using default options
234250
*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.vertx.core.http;
2+
3+
import io.vertx.codegen.annotations.DataObject;
4+
import io.vertx.core.net.QLogConfig;
5+
import io.vertx.core.net.QuicClientOptions;
6+
7+
@DataObject
8+
public class Http3ClientOptions extends QuicClientOptions {
9+
10+
public Http3ClientOptions() {
11+
}
12+
13+
public Http3ClientOptions(Http3ClientOptions other) {
14+
super(other);
15+
}
16+
17+
@Override
18+
public Http3ClientOptions setQLogConfig(QLogConfig qLogConfig) {
19+
return (Http3ClientOptions)super.setQLogConfig(qLogConfig);
20+
}
21+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.vertx.core.http;
2+
3+
import io.vertx.codegen.annotations.DataObject;
4+
import io.vertx.core.net.KeyCertOptions;
5+
import io.vertx.core.net.QLogConfig;
6+
import io.vertx.core.net.QuicServerOptions;
7+
8+
import java.time.Duration;
9+
10+
@DataObject
11+
public class Http3ServerOptions extends QuicServerOptions {
12+
13+
public Http3ServerOptions() {
14+
}
15+
16+
public Http3ServerOptions(Http3ServerOptions other) {
17+
super(other);
18+
}
19+
20+
@Override
21+
public Http3ServerOptions setQLogConfig(QLogConfig qLogConfig) {
22+
return (Http3ServerOptions)super.setQLogConfig(qLogConfig);
23+
}
24+
25+
@Override
26+
public Http3ServerOptions setLoadBalanced(boolean loadBalanced) {
27+
return (Http3ServerOptions)super.setLoadBalanced(loadBalanced);
28+
}
29+
30+
@Override
31+
public Http3ServerOptions setValidateClientAddress(boolean validateClientAddress) {
32+
return (Http3ServerOptions)super.setValidateClientAddress(validateClientAddress);
33+
}
34+
35+
@Override
36+
public Http3ServerOptions setClientAddressValidationTimeWindow(Duration clientAddressValidationTimeWindow) {
37+
return (Http3ServerOptions)super.setClientAddressValidationTimeWindow(clientAddressValidationTimeWindow);
38+
}
39+
40+
@Override
41+
public Http3ServerOptions setClientAddressValidationKey(KeyCertOptions validationKey) {
42+
return (Http3ServerOptions)super.setClientAddressValidationKey(validationKey);
43+
}
44+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.http.impl;
12+
13+
import io.netty.handler.codec.http3.Http3;
14+
import io.vertx.core.Future;
15+
import io.vertx.core.Promise;
16+
import io.vertx.core.http.Http3ClientOptions;
17+
import io.vertx.core.http.impl.http3.Http3ClientConnection;
18+
import io.vertx.core.internal.ContextInternal;
19+
import io.vertx.core.internal.VertxInternal;
20+
import io.vertx.core.internal.quic.QuicConnectionInternal;
21+
import io.vertx.core.net.*;
22+
import io.vertx.core.spi.metrics.ClientMetrics;
23+
24+
import java.time.Duration;
25+
import java.util.Arrays;
26+
import java.util.concurrent.locks.Lock;
27+
import java.util.concurrent.locks.ReentrantLock;
28+
29+
public class Http3ChannelConnector implements HttpChannelConnector {
30+
31+
private final VertxInternal vertx;
32+
private final Lock lock;
33+
private Future<QuicClient> clientFuture;
34+
private final Http3ClientOptions options;
35+
36+
public Http3ChannelConnector(VertxInternal vertxInternal, Http3ClientOptions options) {
37+
38+
options = new Http3ClientOptions(options);
39+
options.getSslOptions().setApplicationLayerProtocols(Arrays.asList(Http3.supportedApplicationProtocols()));
40+
options.getTransportOptions().setInitialMaxData(10000000L);
41+
options.getTransportOptions().setInitialMaxStreamDataBidirectionalLocal(1000000L);
42+
options.getTransportOptions().setInitialMaxStreamDataBidirectionalRemote(1000000L);
43+
options.getTransportOptions().setInitialMaxStreamDataUnidirectional(1000000L);
44+
options.getTransportOptions().setInitialMaxStreamsBidirectional(100L);
45+
options.getTransportOptions().setInitialMaxStreamsUnidirectional(100L);
46+
47+
this.vertx = vertxInternal;
48+
this.lock = new ReentrantLock();
49+
this.options = options;
50+
}
51+
52+
@Override
53+
public Future<HttpClientConnection> httpConnect(ContextInternal context, SocketAddress server, HostAndPort authority, HttpConnectParams params, long maxLifetimeMillis, ClientMetrics<?, ?, ?> metrics) {
54+
55+
lock.lock();
56+
Future<QuicClient> fut = clientFuture;
57+
if (fut == null) {
58+
QuicClient client = QuicClient.create(vertx, this.options);
59+
fut = client.bind(SocketAddress.inetSocketAddress(0, "localhost")).map(client);
60+
clientFuture = fut;
61+
lock.unlock();
62+
} else {
63+
lock.unlock();
64+
}
65+
Promise<HttpClientConnection> promise = context.promise();
66+
67+
fut.onComplete((res, err) -> {
68+
if (err == null) {
69+
Future<QuicConnection> f = res.connect(server);
70+
f.onComplete((res2, err2) -> {
71+
if (err2 == null) {
72+
Http3ClientConnection c = new Http3ClientConnection((QuicConnectionInternal) res2);
73+
c.init();
74+
promise.complete(c);
75+
} else {
76+
promise.fail(err2);
77+
}
78+
});
79+
} else {
80+
promise.fail(err);
81+
}
82+
});
83+
84+
return promise.future();
85+
}
86+
87+
@Override
88+
public Future<Void> shutdown(Duration timeout) {
89+
if (clientFuture == null) {
90+
return vertx.getOrCreateContext().succeededFuture();
91+
} else {
92+
return clientFuture.compose(client -> client.shutdown(timeout));
93+
}
94+
}
95+
96+
@Override
97+
public Future<Void> close() {
98+
if (clientFuture == null) {
99+
return vertx.getOrCreateContext().succeededFuture();
100+
} else {
101+
return clientFuture.compose(QuicEndpoint::close);
102+
}
103+
}
104+
}

vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientImpl.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@
4545
*/
4646
public class HttpClientImpl extends HttpClientBase implements HttpClientInternal, MetricsProvider {
4747

48-
static class Config {
49-
List<String> nonProxyHosts;
50-
boolean verifyHost;
51-
boolean defaultSsl;
52-
String defaultHost;
53-
int defaultPort;
54-
int maxRedirects;
55-
int initialPoolKind;
48+
public static class Config {
49+
public List<String> nonProxyHosts;
50+
public boolean verifyHost;
51+
public boolean defaultSsl;
52+
public String defaultHost;
53+
public int defaultPort;
54+
public int maxRedirects;
55+
public int initialPoolKind;
5656
}
5757

5858
// Pattern to check we are not dealing with an absoluate URI

0 commit comments

Comments
 (0)