Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTTP/3 initial settings #3152

Merged
merged 1 commit into from
Apr 16, 2024
Merged
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
@@ -0,0 +1,217 @@
/*
* Copyright (c) 2024 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed 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
*
* https://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 reactor.netty.http;

/**
* A configuration builder to fine tune the HTTP/3 settings.
*
* @author Violeta Georgieva
* @since 1.2.0
*/
public final class Http3SettingsSpec {

public interface Builder {

/**
* Build a new {@link Http3SettingsSpec}.
*
* @return a new {@link Http3SettingsSpec}
*/
Http3SettingsSpec build();

/**
* Set the initial maximum data limit.
* See <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_data">
* set_initial_max_data</a>.
* Default to {@link Build#DEFAULT_MAX_DATA}
*
* @param maxData the initial maximum data limit
* @return {@code this}
*/
Builder maxData(long maxData);

/**
* Set the initial maximum data limit for local bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_local">
* set_initial_max_stream_data_bidi_local</a>.
* Default to {@link Build#DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL}
*
* @param maxStreamDataBidirectionalLocal the initial maximum data limit for local bidirectional streams
* @return {@code this}
*/
Builder maxStreamDataBidirectionalLocal(long maxStreamDataBidirectionalLocal);

/**
* Set the initial maximum data limit for remote bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_remote">
* set_initial_max_stream_data_bidi_remote</a>.
* Default to {@link Build#DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE}
*
* @param maxStreamDataBidirectionalRemote the initial maximum data limit for remote bidirectional streams
* @return {@code this}
*/
Builder maxStreamDataBidirectionalRemote(long maxStreamDataBidirectionalRemote);

/**
* Set the initial maximum stream limit for bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_streams_bidi">
* set_initial_max_streams_bidi</a>.
* Default to {@link Build#DEFAULT_MAX_STREAMS_BIDIRECTIONAL}
*
* @param maxStreamsBidirectional the initial maximum stream limit for bidirectional streams
* @return {@code this}
*/
Builder maxStreamsBidirectional(long maxStreamsBidirectional);
}

/**
* Creates a builder for {@link Http3SettingsSpec}.
*
* @return a new {@link Http3SettingsSpec.Builder}
*/
public static Http3SettingsSpec.Builder builder() {
return new Http3SettingsSpec.Build();
}

/**
* Return the configured initial maximum data limit.
*
* @return the configured initial maximum data limit
*/
public long maxData() {
return maxData;
}

/**
* Return the configured initial maximum data limit for local bidirectional streams.
*
* @return the configured initial maximum data limit for local bidirectional streams
*/
public long maxStreamDataBidirectionalLocal() {
return maxStreamDataBidirectionalLocal;
}

/**
* Return the configured initial maximum data limit for remote bidirectional streams.
*
* @return the configured initial maximum data limit for remote bidirectional streams
*/
public long maxStreamDataBidirectionalRemote() {
return maxStreamDataBidirectionalRemote;
}

/**
* Return the configured initial maximum stream limit for bidirectional streams.
*
* @return the configured initial maximum stream limit for bidirectional streams
*/
public long maxStreamsBidirectional() {
return maxStreamsBidirectional;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Http3SettingsSpec)) {
return false;
}
Http3SettingsSpec that = (Http3SettingsSpec) o;
return maxData == that.maxData &&
maxStreamDataBidirectionalLocal == that.maxStreamDataBidirectionalLocal &&
maxStreamDataBidirectionalRemote == that.maxStreamDataBidirectionalRemote &&
maxStreamsBidirectional == that.maxStreamsBidirectional;
}

@Override
public int hashCode() {
int result = 1;
result = 31 * result + Long.hashCode(maxData);
result = 31 * result + Long.hashCode(maxStreamDataBidirectionalLocal);
result = 31 * result + Long.hashCode(maxStreamDataBidirectionalRemote);
result = 31 * result + Long.hashCode(maxStreamsBidirectional);
return result;
}

final long maxData;
final long maxStreamDataBidirectionalLocal;
final long maxStreamDataBidirectionalRemote;
final long maxStreamsBidirectional;

Http3SettingsSpec(Build build) {
this.maxData = build.maxData;
this.maxStreamDataBidirectionalLocal = build.maxStreamDataBidirectionalLocal;
this.maxStreamDataBidirectionalRemote = build.maxStreamDataBidirectionalRemote;
this.maxStreamsBidirectional = build.maxStreamsBidirectional;
}

static final class Build implements Builder {
static final long DEFAULT_MAX_DATA = 0L;
static final long DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL = 0L;
static final long DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE = 0L;
static final long DEFAULT_MAX_STREAMS_BIDIRECTIONAL = 0L;

long maxData = DEFAULT_MAX_DATA;
long maxStreamDataBidirectionalLocal = DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL;
long maxStreamDataBidirectionalRemote = DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE;
long maxStreamsBidirectional = DEFAULT_MAX_STREAMS_BIDIRECTIONAL;

@Override
public Http3SettingsSpec build() {
return new Http3SettingsSpec(this);
}

@Override
public Builder maxData(long maxData) {
if (maxData < 0) {
throw new IllegalArgumentException("maxData must be positive or zero");
}
this.maxData = maxData;
return this;
}

@Override
public Builder maxStreamDataBidirectionalLocal(long maxStreamDataBidirectionalLocal) {
if (maxStreamDataBidirectionalLocal < 0) {
throw new IllegalArgumentException("maxStreamDataBidirectionalLocal must be positive or zero");
}
this.maxStreamDataBidirectionalLocal = maxStreamDataBidirectionalLocal;
return this;
}

@Override
public Builder maxStreamDataBidirectionalRemote(long maxStreamDataBidirectionalRemote) {
if (maxStreamDataBidirectionalRemote < 0) {
throw new IllegalArgumentException("maxStreamDataBidirectionalRemote must be positive or zero");
}
this.maxStreamDataBidirectionalRemote = maxStreamDataBidirectionalRemote;
return this;
}

@Override
public Builder maxStreamsBidirectional(long maxStreamsBidirectional) {
if (maxStreamsBidirectional < 0) {
throw new IllegalArgumentException("maxStreamsBidirectional must be positive or zero");
}
this.maxStreamsBidirectional = maxStreamsBidirectional;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import reactor.netty.ConnectionObserver;
import reactor.netty.channel.ChannelMetricsRecorder;
import reactor.netty.http.Http2SettingsSpec;
import reactor.netty.http.Http3SettingsSpec;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.logging.HttpMessageLogFactory;
import reactor.netty.http.logging.ReactorNettyHttpMessageLogFactory;
Expand Down Expand Up @@ -454,6 +455,26 @@ public final HttpServer http2Settings(Consumer<Http2SettingsSpec.Builder> http2S
return dup;
}

/**
* Apply HTTP/3 configuration.
*
* @param http3Settings configures {@link Http3SettingsSpec} before requesting
* @return a new {@link HttpServer}
* @since 1.2.0
*/
public final HttpServer http3Settings(Consumer<Http3SettingsSpec.Builder> http3Settings) {
Objects.requireNonNull(http3Settings, "http3Settings");
Http3SettingsSpec.Builder builder = Http3SettingsSpec.builder();
http3Settings.accept(builder);
Http3SettingsSpec settings = builder.build();
if (settings.equals(configuration().http3Settings)) {
return this;
}
HttpServer dup = duplicate();
dup.configuration().http3Settings = settings;
return dup;
}

/**
* Apply HTTP form decoder configuration.
* The configuration is used when {@link HttpServerRequest#receiveForm()} is invoked.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import reactor.netty.channel.ChannelMetricsRecorder;
import reactor.netty.channel.ChannelOperations;
import reactor.netty.http.Http2SettingsSpec;
import reactor.netty.http.Http3SettingsSpec;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.HttpResources;
import reactor.netty.http.logging.HttpMessageLogFactory;
Expand Down Expand Up @@ -159,6 +160,16 @@ public Http2SettingsSpec http2SettingsSpec() {
return http2Settings;
}

/**
* Return the HTTP/3 configuration.
*
* @return the HTTP/3 configuration
* @since 1.2.0
*/
public Http3SettingsSpec http3SettingsSpec() {
return http3Settings;
}

/**
* Return the configured idle timeout for the connection when it is waiting for an HTTP request or null.
*
Expand Down Expand Up @@ -299,6 +310,7 @@ public Function<String, String> uriTagValue() {
HttpServerFormDecoderProvider formDecoderProvider;
BiFunction<ConnectionInfo, HttpRequest, ConnectionInfo> forwardedHeaderHandler;
Http2SettingsSpec http2Settings;
Http3SettingsSpec http3Settings;
HttpMessageLogFactory httpMessageLogFactory;
Duration idleTimeout;
BiFunction<? super Mono<Void>, ? super Connection, ? extends Mono<Void>>
Expand Down Expand Up @@ -341,6 +353,7 @@ public Function<String, String> uriTagValue() {
this.formDecoderProvider = parent.formDecoderProvider;
this.forwardedHeaderHandler = parent.forwardedHeaderHandler;
this.http2Settings = parent.http2Settings;
this.http3Settings = parent.http3Settings;
this.httpMessageLogFactory = parent.httpMessageLogFactory;
this.idleTimeout = parent.idleTimeout;
this.mapHandle = parent.mapHandle;
Expand Down Expand Up @@ -1214,6 +1227,7 @@ static final class HttpServerChannelInitializer implements ChannelPipelineConfig
final HttpServerFormDecoderProvider formDecoderProvider;
final BiFunction<ConnectionInfo, HttpRequest, ConnectionInfo> forwardedHeaderHandler;
final Http2SettingsSpec http2SettingsSpec;
final Http3SettingsSpec http3SettingsSpec;
final HttpMessageLogFactory httpMessageLogFactory;
final Duration idleTimeout;
final BiFunction<? super Mono<Void>, ? super Connection, ? extends Mono<Void>>
Expand Down Expand Up @@ -1242,6 +1256,7 @@ static final class HttpServerChannelInitializer implements ChannelPipelineConfig
this.formDecoderProvider = config.formDecoderProvider;
this.forwardedHeaderHandler = config.forwardedHeaderHandler;
this.http2SettingsSpec = config.http2Settings;
this.http3SettingsSpec = config.http3Settings;
this.httpMessageLogFactory = config.httpMessageLogFactory;
this.idleTimeout = config.idleTimeout;
this.mapHandle = config.mapHandle;
Expand Down
Loading