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
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public final class Http2Settings extends HttpSettings {
* Default constructor
*/
public Http2Settings() {
super(7);
super(9);
extraSettings = DEFAULT_EXTRA_SETTINGS;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class Http3Settings extends HttpSettings {
}

public Http3Settings() {
super(8);
super(9);
}

public Http3Settings(Http3Settings other) {
Expand Down
14 changes: 14 additions & 0 deletions vertx-core/src/main/java/io/vertx/core/http/HttpClientRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,20 @@ public interface HttpClientRequest extends WriteStream<Buffer> {
@CacheReturn
MultiMap headers();

/**
* @return the pseudo header {@code :protocol} to use for extended connect
*/
String connectProtocol();

/**
* Set the {@code :protocol} pseudo header used for extended connect.
*
* @param protocol the pseudo header value
* @return a reference to this, so the API can be used fluently
*/
@Fluent
HttpClientRequest connectProtocol(String protocol);

/**
* Put an HTTP header
*
Expand Down
6 changes: 6 additions & 0 deletions vertx-core/src/main/java/io/vertx/core/http/HttpHeaders.java
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,12 @@ public interface HttpHeaders {
@GenIgnore(GenIgnore.PERMITTED_TYPE)
CharSequence PSEUDO_METHOD = Http2Headers.PseudoHeaderName.METHOD.value();

/**
* HTTP/2 {@code :protocol} pseudo header
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
CharSequence PSEUDO_PROTOCOL = Http2Headers.PseudoHeaderName.PROTOCOL.value();

/**
* Create an optimized {@link CharSequence} which can be used as header name or value.
* This should be used if you expect to use it multiple times liked for example adding the same header name or value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ default boolean isSSL() {
@Nullable
HostAndPort authority(boolean real);

/**
* @return the {@code :protocol} pseudo header used by extended connect
*/
String connectProtocol();

/**
* @return the total number of bytes read for the body of the request.
*/
Expand Down
17 changes: 17 additions & 0 deletions vertx-core/src/main/java/io/vertx/core/http/HttpSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
*/
package io.vertx.core.http;

import io.netty.handler.codec.http2.Http2CodecUtil;
import io.vertx.codegen.annotations.DataObject;
import io.vertx.core.impl.Arguments;

import java.util.Arrays;
import java.util.Set;
import java.util.function.LongConsumer;

/**
* Base container for HTTP settings.
Expand All @@ -22,6 +26,19 @@
@DataObject
public abstract class HttpSettings {

/**
* HTTP {@code ENABLE_CONNECT_PROTOCOL} setting
*/
public static final HttpSetting<Boolean> ENABLE_CONNECT_PROTOCOL;

static {
LongConsumer enableConnectProtocolValidator = value -> Arguments.require(value == 0L || value == 1L,
"enableConnectProtocol must be >= " + Http2CodecUtil.MIN_HEADER_LIST_SIZE);
ENABLE_CONNECT_PROTOCOL = new HttpSetting<>(0x08, "ENABLE_CONNECT_PROTOCOL", false,
val -> val ? 1L : 0L, val -> val == 1L, enableConnectProtocolValidator, Set.of(HttpVersion.HTTP_2, HttpVersion.HTTP_3));

}

private long presence; // Could be first element of values
private final long[] values;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
private int maxRedirects;
private int numberOfRedirections;
private final MultiMap headers;
private String connectProtocol;
private boolean trailersSent;
private boolean headersSent;
private StreamPriority priority;
Expand Down Expand Up @@ -186,6 +187,17 @@ public MultiMap headers() {
return headers;
}

@Override
public String connectProtocol() {
return connectProtocol;
}

@Override
public HttpClientRequestImpl connectProtocol(String protocol) {
this.connectProtocol = protocol;
return this;
}

@Override
public synchronized HttpClientRequest putHeader(String name, String value) {
checkEnded();
Expand Down Expand Up @@ -533,7 +545,7 @@ private Future<Void> doWrite(Buffer buff, boolean end, boolean connect) {
if (uri.isEmpty()) {
uri = "/";
}
HttpRequestHead head = new HttpRequestHead(ssl ? "https" : "http", method, uri, headers, authority(), absoluteURI(), traceOperation);
HttpRequestHead head = new HttpRequestHead(ssl ? "https" : "http", method, uri, connectProtocol, headers, authority(), absoluteURI(), traceOperation);
future = stream.writeHead(head, chunked, buff, writeEnd, priority, connect);
} else {
if (buff == null && !end) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ public MultiMap headers() {
return headers;
}

@Override
public String connectProtocol() {
return null;
}

@Override
public HttpClientRequest connectProtocol(String protocol) {
throw new IllegalStateException();
}

@Override
public Future<Void> write(Buffer data) {
throw new IllegalStateException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ public class HttpRequestHead {
public final String scheme;
public final HttpMethod method;
public final String uri;
public final String protocol;
public final MultiMap headers;
public final HostAndPort authority;
public final String absoluteURI;
public final String traceOperation;

public HttpRequestHead(String scheme, HttpMethod method, String uri, MultiMap headers, HostAndPort authority, String absoluteURI, String traceOperation) {
public HttpRequestHead(String scheme, HttpMethod method, String uri, String protocol, MultiMap headers, HostAndPort authority, String absoluteURI, String traceOperation) {
this.scheme = scheme;
this.method = method;
this.uri = uri;
this.protocol = protocol;
this.headers = headers;
this.authority = authority;
this.absoluteURI = absoluteURI;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class HttpServerRequestImpl extends HttpServerRequestBase {
private String uri;
private MultiMap headersMap;
private HostAndPort authority;
private String protocol;
private HostAndPort realAuthority;
private String absoluteURI;
private MultiMap attributes;
Expand Down Expand Up @@ -112,6 +113,7 @@ public void handleHeaders(HttpRequestHead headers) {
method = headers.method();
realAuthority = headers.authority;
authority = headers.authority;
protocol = headers.protocol;
if (authority == null) {
String hostHeader = headers.headers.get(HttpHeaders.HOST);
if (hostHeader != null) {
Expand Down Expand Up @@ -359,6 +361,11 @@ public String scheme() {
return real ? realAuthority : authority;
}

@Override
public String connectProtocol() {
return protocol;
}

@Override
public long bytesRead() {
return stream.bytesRead();
Expand Down
13 changes: 12 additions & 1 deletion vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.vertx.core.file.OpenOptions;
import io.vertx.core.http.HttpClosedException;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpSettings;
import io.vertx.core.http.StreamPriority;
import io.vertx.core.internal.ContextInternal;
import io.vertx.core.internal.VertxInternal;
Expand Down Expand Up @@ -379,6 +380,12 @@ private static void fromVertxInitialSettings(boolean server, io.vertx.core.http.
if (vertxSettings.getMaxHeaderListSize() != DEFAULT_MAX_HEADER_LIST_SIZE) {
nettySettings.maxHeaderListSize(vertxSettings.getMaxHeaderListSize());
}
if (vertxSettings.getMaxHeaderListSize() != DEFAULT_MAX_HEADER_LIST_SIZE) {
nettySettings.maxHeaderListSize(vertxSettings.getMaxHeaderListSize());
}
if (vertxSettings.get(HttpSettings.ENABLE_CONNECT_PROTOCOL) == Boolean.TRUE) {
nettySettings.put((char)0x08, (Long)1L);
}
Map<Integer, Long> extraSettings = vertxSettings.getExtraSettings();
if (extraSettings != null) {
extraSettings.forEach((code, setting) -> {
Expand Down Expand Up @@ -429,8 +436,12 @@ public static io.vertx.core.http.Http2Settings toVertxSettings(Http2Settings set
if (headerTableSize != null) {
converted.setHeaderTableSize(headerTableSize);
}
Long enableConnectProtocol = settings.get((char)0x08);
if (enableConnectProtocol != null && enableConnectProtocol == 1L) {
converted.set(HttpSettings.ENABLE_CONNECT_PROTOCOL, true);
}
settings.forEach((key, value) -> {
if (key > 6) {
if (key > 6 && key != 8) {
converted.set(key, value);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public String value(HttpRequestHeaders req, int index) {
private HostAndPort authority;
private String uri;
private String scheme;
private String protocol;
private String trace;

public HttpRequestHeaders(Headers<CharSequence, CharSequence, ?> headers) {
Expand Down Expand Up @@ -167,6 +168,15 @@ public HttpHeaders trace(String trace) {
return this;
}

public String protocol() {
return protocol;
}

public HttpHeaders protocol(String protocol) {
this.protocol = protocol;
return this;
}

public boolean validate() {
CharSequence methodHeader = headers.get(io.vertx.core.http.HttpHeaders.PSEUDO_METHOD);
if (methodHeader == null) {
Expand Down Expand Up @@ -197,7 +207,15 @@ public boolean validate() {
authorityPresence = authority;
}

if (method == HttpMethod.CONNECT) {
CharSequence protocolHeader = headers.get(io.vertx.core.http.HttpHeaders.PSEUDO_PROTOCOL);
String protocol;
if (method == HttpMethod.CONNECT && protocolHeader != null) {
protocol = protocolHeader.toString();
} else {
protocol = null;
}

if (method == HttpMethod.CONNECT && protocol == null) {
if (scheme != null || uri != null || authorityPresence == null) {
return false;
}
Expand Down Expand Up @@ -225,6 +243,7 @@ public boolean validate() {
this.uri = uri;
this.authority = authority;
this.scheme = scheme;
this.protocol = protocol;

return true;
}
Expand Down Expand Up @@ -254,6 +273,9 @@ public void prepare() {
if (scheme != null) {
headers.set(io.vertx.core.http.HttpHeaders.PSEUDO_SCHEME, scheme);
}
if (method == HttpMethod.CONNECT && protocol != null) {
headers.set(io.vertx.core.http.HttpHeaders.PSEUDO_PROTOCOL, protocol);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ public synchronized void toWebSocket(

if (webSocketMetrics != null) {
ws.setMetric(webSocketMetrics.connected(new ObservableRequest(new HttpRequestHead(
ssl ? "https" : "http", HttpMethod.GET, requestURI, headers, authority, "/", null
ssl ? "https" : "http", HttpMethod.GET, requestURI, null, headers, authority, "/", null
))));
}
ws.pause();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ public HostAndPort authority(boolean real) {
return real ? null : authority();
}

@Override
public String connectProtocol() {
return null;
}

@Override
public long bytesRead() {
synchronized (conn) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public void write() {
throw new IllegalArgumentException("Missing :authority / host header");
}
headers.authority(request.authority);
if (request.protocol != null) {
headers.protocol(request.protocol);
headers.path(request.uri);
headers.scheme(connection.isSsl() ? "https" : "http");
}
// don't end stream for CONNECT
e = false;
} else {
Expand Down Expand Up @@ -217,7 +222,7 @@ public void onPush(Http2ClientStream pushStream, int promisedStreamId, HttpHeade
}

public void onPush(DefaultHttp2ClientStream pushStream, int promisedStreamId, HttpRequestHeaders headers, boolean writable) {
HttpClientPush push = new HttpClientPush(new HttpRequestHead(headers.scheme(), headers.method(), headers.path(), headers, headers.authority(), null, null), pushStream);
HttpClientPush push = new HttpClientPush(new HttpRequestHead(headers.scheme(), headers.method(), headers.path(), null, headers, headers.authority(), null, null), pushStream);
pushStream.init(promisedStreamId, writable);
if (pushStream.observable != null) {
pushStream.observable.observePush(headers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ void handleHeader(HttpHeaders map) {
requestHeaders.scheme(),
requestHeaders.method(),
requestHeaders.path(),
requestHeaders.protocol(),
map,
requestHeaders.authority(),
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ public Future<Void> writeHead(HttpRequestHead request, boolean chunked, Buffer c
if (request.method != HttpMethod.CONNECT) {
headers.path(request.uri);
headers.scheme("https");
} else {
if (request.protocol != null) {
headers.path(request.uri);
headers.scheme("https");
headers.protocol(request.protocol);
}
}
headers.prepare();
return writeHeaders(headers, chunk, end);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,19 @@ public Http3Connection(QuicConnectionInternal connection, Http3Settings localSet

io.netty.handler.codec.http3.Http3Settings nettyLocalSettings() {
io.netty.handler.codec.http3.Http3Settings nSettings = new io.netty.handler.codec.http3.Http3Settings();
Long val;
if ((val = localSettings.get(Http3Settings.MAX_FIELD_SECTION_SIZE)) != null) {
nSettings.maxFieldSectionSize(val);
Long lval;
if ((lval = localSettings.get(Http3Settings.MAX_FIELD_SECTION_SIZE)) != null) {
nSettings.maxFieldSectionSize(lval);
}
if ((val = localSettings.get(Http3Settings.QPACK_BLOCKED_STREAMS)) != null) {
nSettings.qpackBlockedStreams(val);
if ((lval = localSettings.get(Http3Settings.QPACK_BLOCKED_STREAMS)) != null) {
nSettings.qpackBlockedStreams(lval);
}
if ((val = localSettings.get(Http3Settings.QPACK_MAX_TABLE_CAPACITY)) != null) {
nSettings.qpackMaxTableCapacity(val);
if ((lval = localSettings.get(Http3Settings.QPACK_MAX_TABLE_CAPACITY)) != null) {
nSettings.qpackMaxTableCapacity(lval);
}
Boolean bval;
if ((bval = localSettings.get(HttpSettings.ENABLE_CONNECT_PROTOCOL)) != null) {
nSettings.enableConnectProtocol(bval);
}
return nSettings;
}
Expand Down Expand Up @@ -250,6 +254,9 @@ private void handleSettings(io.netty.handler.codec.http3.Http3Settings nSettings
case HTTP3_SETTINGS_MAX_FIELD_SECTION_SIZE:
vSetting = Http3Settings.MAX_FIELD_SECTION_SIZE;
break;
case HTTP3_SETTINGS_ENABLE_CONNECT_PROTOCOL:
vSetting = HttpSettings.ENABLE_CONNECT_PROTOCOL;
break;
default:
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected boolean handleHead(HttpHeaders headers) {
requestHeaders.scheme(),
requestHeaders.method(),
requestHeaders.path(),
requestHeaders.protocol(),
requestHeaders,
requestHeaders.authority(),
null,
Expand Down
Loading
Loading