All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.webserver.http2.Http2Config Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 2024 Oracle and/or its affiliates.
 *
 * 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
 *
 *     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 io.helidon.webserver.http2;

import java.time.Duration;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

import io.helidon.builder.api.Prototype;
import io.helidon.common.Errors;
import io.helidon.common.Generated;
import io.helidon.common.config.Config;
import io.helidon.http.RequestedUriDiscoveryContext;

/**
 * HTTP/2 server configuration.
 *
 * @see #builder()
 * @see #create()
 */
@Generated(value = "io.helidon.builder.codegen.BuilderCodegen", trigger = "io.helidon.webserver.http2.Http2ConfigBlueprint")
public interface Http2Config extends Http2ConfigBlueprint, Prototype.Api {

    /**
     * Create a new fluent API builder to customize configuration.
     *
     * @return a new builder
     */
    static Http2Config.Builder builder() {
        return new Http2Config.Builder();
    }

    /**
     * Create a new fluent API builder from an existing instance.
     *
     * @param instance an existing instance used as a base for the builder
     * @return a builder based on an instance
     */
    static Http2Config.Builder builder(Http2Config instance) {
        return Http2Config.builder().from(instance);
    }

    /**
     * Create a new instance from configuration.
     *
     * @param config used to configure the new instance
     * @return a new instance configured from configuration
     */
    static Http2Config create(Config config) {
        return Http2Config.builder().config(config).buildPrototype();
    }

    /**
     * Create a new instance with default values.
     *
     * @return a new instance
     */
    static Http2Config create() {
        return Http2Config.builder().buildPrototype();
    }

    /**
     * Fluent API builder base for {@link Http2Config}.
     *
     * @param  type of the builder extending this abstract builder
     * @param  type of the prototype interface that would be built by {@link #buildPrototype()}
     */
    abstract class BuilderBase, PROTOTYPE extends Http2Config> implements Prototype.ConfiguredBuilder {

        private boolean sendErrorDetails = false;
        private boolean validatePath = true;
        private Config config;
        private Duration flowControlTimeout = Duration.parse("PT0.1S");
        private Duration rapidResetCheckPeriod = Duration.parse("PT10S");
        private int initialWindowSize = 1048576;
        private int maxEmptyFrames = 10;
        private int maxFrameSize = 16384;
        private int maxRapidResets = 100;
        private long maxConcurrentStreams = 8192L;
        private long maxHeaderListSize = 8192;
        private RequestedUriDiscoveryContext requestedUriDiscovery;
        private String name;

        /**
         * Protected to support extensibility.
         */
        protected BuilderBase() {
        }

        /**
         * Update this builder from an existing prototype instance. This method disables automatic service discovery.
         *
         * @param prototype existing prototype to update this builder from
         * @return updated builder instance
         */
        public BUILDER from(Http2Config prototype) {
            maxFrameSize(prototype.maxFrameSize());
            maxHeaderListSize(prototype.maxHeaderListSize());
            maxConcurrentStreams(prototype.maxConcurrentStreams());
            initialWindowSize(prototype.initialWindowSize());
            flowControlTimeout(prototype.flowControlTimeout());
            sendErrorDetails(prototype.sendErrorDetails());
            rapidResetCheckPeriod(prototype.rapidResetCheckPeriod());
            maxRapidResets(prototype.maxRapidResets());
            maxEmptyFrames(prototype.maxEmptyFrames());
            validatePath(prototype.validatePath());
            requestedUriDiscovery(prototype.requestedUriDiscovery());
            name(prototype.name());
            return self();
        }

        /**
         * Update this builder from an existing prototype builder instance.
         *
         * @param builder existing builder prototype to update this builder from
         * @return updated builder instance
         */
        public BUILDER from(Http2Config.BuilderBase builder) {
            maxFrameSize(builder.maxFrameSize());
            maxHeaderListSize(builder.maxHeaderListSize());
            maxConcurrentStreams(builder.maxConcurrentStreams());
            initialWindowSize(builder.initialWindowSize());
            flowControlTimeout(builder.flowControlTimeout());
            sendErrorDetails(builder.sendErrorDetails());
            rapidResetCheckPeriod(builder.rapidResetCheckPeriod());
            maxRapidResets(builder.maxRapidResets());
            maxEmptyFrames(builder.maxEmptyFrames());
            validatePath(builder.validatePath());
            builder.requestedUriDiscovery().ifPresent(this::requestedUriDiscovery);
            builder.name().ifPresent(this::name);
            return self();
        }

        /**
         * Update builder from configuration (node of this type).
         * If a value is present in configuration, it would override currently configured values.
         *
         * @param config configuration instance used to obtain values to update this builder
         * @return updated builder instance
         */
        @Override
        public BUILDER config(Config config) {
            Objects.requireNonNull(config);
            this.config = config;
            config.get("max-frame-size").as(Integer.class).ifPresent(this::maxFrameSize);
            config.get("max-header-list-size").as(Long.class).ifPresent(this::maxHeaderListSize);
            config.get("max-concurrent-streams").as(Long.class).ifPresent(this::maxConcurrentStreams);
            config.get("initial-window-size").as(Integer.class).ifPresent(this::initialWindowSize);
            config.get("flow-control-timeout").as(Duration.class).ifPresent(this::flowControlTimeout);
            config.get("send-error-details").as(Boolean.class).ifPresent(this::sendErrorDetails);
            config.get("rapid-reset-check-period").as(Duration.class).ifPresent(this::rapidResetCheckPeriod);
            config.get("max-rapid-resets").as(Integer.class).ifPresent(this::maxRapidResets);
            config.get("max-empty-frames").as(Integer.class).ifPresent(this::maxEmptyFrames);
            config.get("validate-path").as(Boolean.class).ifPresent(this::validatePath);
            config.get("requested-uri-discovery").map(RequestedUriDiscoveryContext::create).ifPresent(this::requestedUriDiscovery);
            return self();
        }

        /**
         * The size of the largest frame payload that the sender is willing to receive in bytes.
         * Default value is {@code 16384} and maximum value is 224-1 = 16777215 bytes.
         * See RFC 9113 section 6.5.2 for details.
         *
         * @param maxFrameSize maximal frame size
         * @return updated builder instance
         * @see #maxFrameSize()
         */
        public BUILDER maxFrameSize(int maxFrameSize) {
            this.maxFrameSize = maxFrameSize;
            return self();
        }

        /**
         * The maximum field section size that the sender is prepared to accept in bytes.
         * See RFC 9113 section 6.5.2 for details.
         * Default is 8192.
         *
         * @param maxHeaderListSize maximal header list size in bytes
         * @return updated builder instance
         * @see #maxHeaderListSize()
         */
        public BUILDER maxHeaderListSize(long maxHeaderListSize) {
            this.maxHeaderListSize = maxHeaderListSize;
            return self();
        }

        /**
         * Maximum number of concurrent streams that the server will allow.
         * Defaults to {@code 8192}. This limit is directional: it applies to the number of streams that the sender
         * permits the receiver to create.
         * It is recommended that this value be no smaller than 100 to not unnecessarily limit parallelism
         * See RFC 9113 section 6.5.2 for details.
         *
         * @param maxConcurrentStreams maximal number of concurrent streams
         * @return updated builder instance
         * @see #maxConcurrentStreams()
         */
        public BUILDER maxConcurrentStreams(long maxConcurrentStreams) {
            this.maxConcurrentStreams = maxConcurrentStreams;
            return self();
        }

        /**
         * This setting indicates the sender's maximum window size in bytes for stream-level flow control.
         * Default and maximum value is 231-1 = 2147483647 bytes. This setting affects the window size
         * of HTTP/2 connection.
         * Any value greater than 2147483647 causes an error. Any value smaller than initial window size causes an error.
         * See RFC 9113 section 6.9.1 for details.
         *
         * @param initialWindowSize maximum window size in bytes
         * @return updated builder instance
         * @see #initialWindowSize()
         */
        public BUILDER initialWindowSize(int initialWindowSize) {
            this.initialWindowSize = initialWindowSize;
            return self();
        }

        /**
         * Outbound flow control blocking timeout configured as {@link java.time.Duration}
         * or text in ISO-8601 format.
         * Blocking timeout defines an interval to wait for the outbound window size changes(incoming window updates)
         * before the next blocking iteration.
         * Default value is {@code PT0.1S}.
         *
         * 
         *     
         *     
         *     
         *     
         * 
ISO_8601 format examples:
PT0.1S100 milliseconds
PT0.5S500 milliseconds
PT2S2 seconds
* * @param flowControlTimeout duration * @return updated builder instance * @see ISO_8601 Durations * @see #flowControlTimeout() */ public BUILDER flowControlTimeout(Duration flowControlTimeout) { Objects.requireNonNull(flowControlTimeout); this.flowControlTimeout = flowControlTimeout; return self(); } /** * Whether to send error message over HTTP to client. * Defaults to {@code false}, as exception message may contain internal information that could be used as an * attack vector. Use with care and in cases where both server and clients are under your full control (such as for * testing). * * @param sendErrorDetails whether to send error messages over the network * @return updated builder instance * @see #sendErrorDetails() */ public BUILDER sendErrorDetails(boolean sendErrorDetails) { this.sendErrorDetails = sendErrorDetails; return self(); } /** * Period for counting rapid resets(stream RST sent by client before any data have been sent by server). * Default value is {@code PT10S}. * * @param rapidResetCheckPeriod duration * @return updated builder instance * @see CVE-2023-44487 * @see ISO_8601 Durations * @see #rapidResetCheckPeriod() */ public BUILDER rapidResetCheckPeriod(Duration rapidResetCheckPeriod) { Objects.requireNonNull(rapidResetCheckPeriod); this.rapidResetCheckPeriod = rapidResetCheckPeriod; return self(); } /** * Maximum number of rapid resets(stream RST sent by client before any data have been sent by server). * When reached within {@link #rapidResetCheckPeriod()}, GOAWAY is sent to client and connection is closed. * Default value is {@code 100}. * * @param maxRapidResets maximum number of rapid resets * @return updated builder instance * @see CVE-2023-44487 * @see #maxRapidResets() */ public BUILDER maxRapidResets(int maxRapidResets) { this.maxRapidResets = maxRapidResets; return self(); } /** * Maximum number of consecutive empty frames allowed on connection. * * @param maxEmptyFrames max number of consecutive empty frames * @return updated builder instance * @see #maxEmptyFrames() */ public BUILDER maxEmptyFrames(int maxEmptyFrames) { this.maxEmptyFrames = maxEmptyFrames; return self(); } /** * If set to false, any path is accepted (even containing illegal characters). * * @param validatePath whether to validate path * @return updated builder instance * @see #validatePath() */ public BUILDER validatePath(boolean validatePath) { this.validatePath = validatePath; return self(); } /** * Requested URI discovery settings. * * @param requestedUriDiscovery settings for computing the requested URI * @return updated builder instance * @see #requestedUriDiscovery() */ public BUILDER requestedUriDiscovery(RequestedUriDiscoveryContext requestedUriDiscovery) { Objects.requireNonNull(requestedUriDiscovery); this.requestedUriDiscovery = requestedUriDiscovery; return self(); } /** * Requested URI discovery settings. * * @param consumer consumer of builder for * settings for computing the requested URI * @return updated builder instance * @see #requestedUriDiscovery() */ public BUILDER requestedUriDiscovery(Consumer consumer) { Objects.requireNonNull(consumer); var builder = RequestedUriDiscoveryContext.builder(); consumer.accept(builder); this.requestedUriDiscovery(builder.build()); return self(); } /** * Requested URI discovery settings. * * @param supplier supplier of * settings for computing the requested URI * @return updated builder instance * @see #requestedUriDiscovery() */ public BUILDER requestedUriDiscovery(Supplier supplier) { Objects.requireNonNull(supplier); this.requestedUriDiscovery(supplier.get()); return self(); } /** * * * @param name * @return updated builder instance * @see #name() */ public BUILDER name(String name) { Objects.requireNonNull(name); this.name = name; return self(); } /** * The size of the largest frame payload that the sender is willing to receive in bytes. * Default value is {@code 16384} and maximum value is 224-1 = 16777215 bytes. * See RFC 9113 section 6.5.2 for details. * * @return the max frame size */ public int maxFrameSize() { return maxFrameSize; } /** * The maximum field section size that the sender is prepared to accept in bytes. * See RFC 9113 section 6.5.2 for details. * Default is 8192. * * @return the max header list size */ public long maxHeaderListSize() { return maxHeaderListSize; } /** * Maximum number of concurrent streams that the server will allow. * Defaults to {@code 8192}. This limit is directional: it applies to the number of streams that the sender * permits the receiver to create. * It is recommended that this value be no smaller than 100 to not unnecessarily limit parallelism * See RFC 9113 section 6.5.2 for details. * * @return the max concurrent streams */ public long maxConcurrentStreams() { return maxConcurrentStreams; } /** * This setting indicates the sender's maximum window size in bytes for stream-level flow control. * Default and maximum value is 231-1 = 2147483647 bytes. This setting affects the window size * of HTTP/2 connection. * Any value greater than 2147483647 causes an error. Any value smaller than initial window size causes an error. * See RFC 9113 section 6.9.1 for details. * * @return the initial window size */ public int initialWindowSize() { return initialWindowSize; } /** * Outbound flow control blocking timeout configured as {@link java.time.Duration} * or text in ISO-8601 format. * Blocking timeout defines an interval to wait for the outbound window size changes(incoming window updates) * before the next blocking iteration. * Default value is {@code PT0.1S}. * * * * * * *
ISO_8601 format examples:
PT0.1S100 milliseconds
PT0.5S500 milliseconds
PT2S2 seconds
* * @return the flow control timeout * @see ISO_8601 Durations * @see #flowControlTimeout() */ public Duration flowControlTimeout() { return flowControlTimeout; } /** * Whether to send error message over HTTP to client. * Defaults to {@code false}, as exception message may contain internal information that could be used as an * attack vector. Use with care and in cases where both server and clients are under your full control (such as for * testing). * * @return the send error details */ public boolean sendErrorDetails() { return sendErrorDetails; } /** * Period for counting rapid resets(stream RST sent by client before any data have been sent by server). * Default value is {@code PT10S}. * * @return the rapid reset check period * @see CVE-2023-44487 * @see ISO_8601 Durations * @see #rapidResetCheckPeriod() */ public Duration rapidResetCheckPeriod() { return rapidResetCheckPeriod; } /** * Maximum number of rapid resets(stream RST sent by client before any data have been sent by server). * When reached within {@link #rapidResetCheckPeriod()}, GOAWAY is sent to client and connection is closed. * Default value is {@code 100}. * * @return the max rapid resets * @see CVE-2023-44487 * @see #maxRapidResets() */ public int maxRapidResets() { return maxRapidResets; } /** * Maximum number of consecutive empty frames allowed on connection. * * @return the max empty frames */ public int maxEmptyFrames() { return maxEmptyFrames; } /** * If set to false, any path is accepted (even containing illegal characters). * * @return the validate path */ public boolean validatePath() { return validatePath; } /** * Requested URI discovery settings. * * @return the requested uri discovery */ public Optional requestedUriDiscovery() { return Optional.ofNullable(requestedUriDiscovery); } /** * * * @return the name */ public Optional name() { return Optional.ofNullable(name); } /** * If this instance was configured, this would be the config instance used. * * @return config node used to configure this builder, or empty if not configured */ public Optional config() { return Optional.ofNullable(config); } @Override public String toString() { return "Http2ConfigBuilder{" + "maxFrameSize=" + maxFrameSize + "," + "maxHeaderListSize=" + maxHeaderListSize + "," + "maxConcurrentStreams=" + maxConcurrentStreams + "," + "initialWindowSize=" + initialWindowSize + "," + "flowControlTimeout=" + flowControlTimeout + "," + "sendErrorDetails=" + sendErrorDetails + "," + "rapidResetCheckPeriod=" + rapidResetCheckPeriod + "," + "maxRapidResets=" + maxRapidResets + "," + "maxEmptyFrames=" + maxEmptyFrames + "," + "validatePath=" + validatePath + "," + "requestedUriDiscovery=" + requestedUriDiscovery + "," + "name=" + name + "}"; } /** * Handles providers and decorators. */ protected void preBuildPrototype() { new Http2ConfigBlueprint.Http2ConfigDecorator().decorate(this); } /** * Validates required properties. */ protected void validatePrototype() { Errors.Collector collector = Errors.collector(); if (requestedUriDiscovery == null) { collector.fatal(getClass(), "Property \"requested-uri-discovery\" must not be null, but not set"); } if (name == null) { collector.fatal(getClass(), "Property \"name\" must not be null, but not set"); } collector.collect().checkValid(); } /** * Generated implementation of the prototype, can be extended by descendant prototype implementations. */ protected static class Http2ConfigImpl implements Http2Config { private final boolean sendErrorDetails; private final boolean validatePath; private final Duration flowControlTimeout; private final Duration rapidResetCheckPeriod; private final int initialWindowSize; private final int maxEmptyFrames; private final int maxFrameSize; private final int maxRapidResets; private final long maxConcurrentStreams; private final long maxHeaderListSize; private final RequestedUriDiscoveryContext requestedUriDiscovery; private final String name; /** * Create an instance providing a builder. * * @param builder extending builder base of this prototype */ protected Http2ConfigImpl(Http2Config.BuilderBase builder) { this.maxFrameSize = builder.maxFrameSize(); this.maxHeaderListSize = builder.maxHeaderListSize(); this.maxConcurrentStreams = builder.maxConcurrentStreams(); this.initialWindowSize = builder.initialWindowSize(); this.flowControlTimeout = builder.flowControlTimeout(); this.sendErrorDetails = builder.sendErrorDetails(); this.rapidResetCheckPeriod = builder.rapidResetCheckPeriod(); this.maxRapidResets = builder.maxRapidResets(); this.maxEmptyFrames = builder.maxEmptyFrames(); this.validatePath = builder.validatePath(); this.requestedUriDiscovery = builder.requestedUriDiscovery().get(); this.name = builder.name().get(); } @Override public int maxFrameSize() { return maxFrameSize; } @Override public long maxHeaderListSize() { return maxHeaderListSize; } @Override public long maxConcurrentStreams() { return maxConcurrentStreams; } @Override public int initialWindowSize() { return initialWindowSize; } @Override public Duration flowControlTimeout() { return flowControlTimeout; } @Override public boolean sendErrorDetails() { return sendErrorDetails; } @Override public Duration rapidResetCheckPeriod() { return rapidResetCheckPeriod; } @Override public int maxRapidResets() { return maxRapidResets; } @Override public int maxEmptyFrames() { return maxEmptyFrames; } @Override public boolean validatePath() { return validatePath; } @Override public RequestedUriDiscoveryContext requestedUriDiscovery() { return requestedUriDiscovery; } @Override public String name() { return name; } @Override public String toString() { return "Http2Config{" + "maxFrameSize=" + maxFrameSize + "," + "maxHeaderListSize=" + maxHeaderListSize + "," + "maxConcurrentStreams=" + maxConcurrentStreams + "," + "initialWindowSize=" + initialWindowSize + "," + "flowControlTimeout=" + flowControlTimeout + "," + "sendErrorDetails=" + sendErrorDetails + "," + "rapidResetCheckPeriod=" + rapidResetCheckPeriod + "," + "maxRapidResets=" + maxRapidResets + "," + "maxEmptyFrames=" + maxEmptyFrames + "," + "validatePath=" + validatePath + "," + "requestedUriDiscovery=" + requestedUriDiscovery + "," + "name=" + name + "}"; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Http2Config other)) { return false; } return maxFrameSize == other.maxFrameSize() && maxHeaderListSize == other.maxHeaderListSize() && maxConcurrentStreams == other.maxConcurrentStreams() && initialWindowSize == other.initialWindowSize() && Objects.equals(flowControlTimeout, other.flowControlTimeout()) && sendErrorDetails == other.sendErrorDetails() && Objects.equals(rapidResetCheckPeriod, other.rapidResetCheckPeriod()) && maxRapidResets == other.maxRapidResets() && maxEmptyFrames == other.maxEmptyFrames() && validatePath == other.validatePath() && Objects.equals(requestedUriDiscovery, other.requestedUriDiscovery()) && Objects.equals(name, other.name()); } @Override public int hashCode() { return Objects.hash(maxFrameSize, maxHeaderListSize, maxConcurrentStreams, initialWindowSize, flowControlTimeout, sendErrorDetails, rapidResetCheckPeriod, maxRapidResets, maxEmptyFrames, validatePath, requestedUriDiscovery, name); } } } /** * Fluent API builder for {@link Http2Config}. */ class Builder extends Http2Config.BuilderBase implements io.helidon.common.Builder { private Builder() { } @Override public Http2Config buildPrototype() { preBuildPrototype(); validatePrototype(); return new Http2ConfigImpl(this); } @Override public Http2Config build() { return buildPrototype(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy