From 81af7b97a7307aa3b98d83fa3cc2c40f04b6456e Mon Sep 17 00:00:00 2001 From: Layla Date: Mon, 4 Dec 2023 15:44:16 +0100 Subject: [PATCH 1/3] Added a functional interface EventLoopSchedulerFactory --- .../armeria/client/EventLoopSchedulerFactory.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java diff --git a/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java b/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java new file mode 100644 index 00000000000..f22392be74f --- /dev/null +++ b/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java @@ -0,0 +1,15 @@ +package com.linecorp.armeria.client; + +import io.netty.channel.EventLoopGroup; + +import java.util.List; +import java.util.function.ToIntFunction; + +@FunctionalInterface +public interface EventLoopSchedulerFactory { + EventLoopScheduler newScheduler(EventLoopGroup eventLoopGroup, + List> maxNumEventLoopFunctions, + int maxNumEventLoopsFunctions, + int maxNumEventLoopsPerHttp1Endpoint, + long idleTimeOutMillis); +} From f1ff6c6ba30a2e18fbc5a7c5ab2c6e1ad27ca315 Mon Sep 17 00:00:00 2001 From: Layla Silbernberg <119636966+LaylaSilbernberg@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:05:21 +0100 Subject: [PATCH 2/3] added new event loop scheduler factory api, deprecated old api, cleaned up code --- .../armeria/client/ClientFactoryBuilder.java | 16 + .../armeria/client/ClientFactoryOptions.java | 1204 +++++++++-------- .../client/EventLoopSchedulerFactory.java | 15 + 3 files changed, 681 insertions(+), 554 deletions(-) create mode 100644 core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java diff --git a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryBuilder.java b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryBuilder.java index 62c93410e38..b8141f2f809 100644 --- a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryBuilder.java @@ -158,7 +158,10 @@ public ClientFactoryBuilder workerGroup(int numThreads) { /** * Sets the factory that creates an {@link EventLoopScheduler} which is responsible for assigning an * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. + * @deprecated This factory method lacks the ability to build a sophisticated scheduler. + * Use the method that requires an EventLoopSchedulerFactory instead. */ + @Deprecated public ClientFactoryBuilder eventLoopSchedulerFactory( Function eventLoopSchedulerFactory) { requireNonNull(eventLoopSchedulerFactory, "eventLoopSchedulerFactory"); @@ -169,6 +172,19 @@ public ClientFactoryBuilder eventLoopSchedulerFactory( return this; } + /** + * Sets the factory that creates an {@link EventLoopScheduler} which is responsible for assigning an + * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. + * @deprecated This factory method lacks the ability to build a sophisticated scheduler. + * Use the method that requires an EventLoopSchedulerFactory instead. + */ + @Deprecated + public ClientFactoryBuilder eventLoopSchedulerFactory(EventLoopSchedulerFactory eventLoopSchedulerFactory){ + requireNonNull(eventLoopSchedulerFactory, "eventLoopSchedulerFactory"); + option(ClientFactoryOptions.CUSTOM_EVENT_LOOP_SCHEDULER_FACTORY, eventLoopSchedulerFactory); + return this; + } + /** * Sets the maximum number of {@link EventLoop}s which will be used to handle HTTP/1.1 connections * except the ones specified by {@link #maxNumEventLoopsFunction(ToIntFunction)}. diff --git a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java index eeac4c9fa53..03de20e1766 100644 --- a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java +++ b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java @@ -51,561 +51,657 @@ * A set of {@link ClientFactoryOption}s and their respective values. */ public final class ClientFactoryOptions - extends AbstractOptions, ClientFactoryOptionValue> { - - /** - * The worker {@link EventLoopGroup}. - */ - public static final ClientFactoryOption WORKER_GROUP = - ClientFactoryOption.define("WORKER_GROUP", CommonPools.workerGroup()); - - /** - * Whether to shut down the worker {@link EventLoopGroup} when the {@link ClientFactory} is closed. - */ - public static final ClientFactoryOption SHUTDOWN_WORKER_GROUP_ON_CLOSE = - ClientFactoryOption.define("SHUTDOWN_WORKER_GROUP_ON_CLOSE", false); - - /** - * The factory that creates an {@link EventLoopScheduler} which is responsible for assigning an - * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. - */ - public static final ClientFactoryOption> - EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption.define( - "EVENT_LOOP_SCHEDULER_FACTORY", - eventLoopGroup -> new DefaultEventLoopScheduler(eventLoopGroup, 0, 0, ImmutableList.of())); - - /** - * The {@link Consumer} which can arbitrarily configure the {@link SslContextBuilder} that will be - * applied to the SSL session. - */ - public static final ClientFactoryOption> TLS_CUSTOMIZER = - ClientFactoryOption.define("TLS_CUSTOMIZER", b -> { /* no-op */ }); - - /** - * Whether to allow the bad cipher suites listed in - * RFC7540 for TLS handshake. - * - *

Note that enabling this option increases the security risk of your connection. - * Use it only when you must communicate with a legacy system that does not support - * secure cipher suites. - * See Section 9.2.2, RFC7540 for - * more information. - * - * @deprecated It's not recommended to enable this option. Use it only when you have no other way to - * communicate with an insecure peer than this. - */ - @Deprecated - public static final ClientFactoryOption TLS_ALLOW_UNSAFE_CIPHERS = - ClientFactoryOption.define("tlsAllowUnsafeCiphers", Flags.tlsAllowUnsafeCiphers()); - - /** - * The factory that creates an {@link AddressResolverGroup} which resolves remote addresses into - * {@link InetSocketAddress}es. - */ - public static final ClientFactoryOption>> ADDRESS_RESOLVER_GROUP_FACTORY = - ClientFactoryOption.define("ADDRESS_RESOLVER_GROUP_FACTORY", - eventLoopGroup -> new DnsResolverGroupBuilder().build(eventLoopGroup)); - - /** - * The HTTP/2 initial connection flow-control - * window size. - */ - public static final ClientFactoryOption HTTP2_INITIAL_CONNECTION_WINDOW_SIZE = - ClientFactoryOption.define("HTTP2_INITIAL_CONNECTION_WINDOW_SIZE", - Flags.defaultHttp2InitialConnectionWindowSize()); - - /** - * The SETTINGS_INITIAL_WINDOW_SIZE - * for HTTP/2 stream-level flow control. - */ - public static final ClientFactoryOption HTTP2_INITIAL_STREAM_WINDOW_SIZE = - ClientFactoryOption.define("HTTP2_INITIAL_STREAM_WINDOW_SIZE", - Flags.defaultHttp2InitialStreamWindowSize()); - - /** - * The SETTINGS_MAX_FRAME_SIZE - * that indicates the size of the largest frame payload that this client is willing to receive. - */ - public static final ClientFactoryOption HTTP2_MAX_FRAME_SIZE = - ClientFactoryOption.define("HTTP2_MAX_FRAME_SIZE", Flags.defaultHttp2MaxFrameSize()); - - /** - * The HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE - * that indicates the maximum size of header list that the client is prepared to accept, in octets. - */ - public static final ClientFactoryOption HTTP2_MAX_HEADER_LIST_SIZE = - ClientFactoryOption.define("HTTP2_MAX_HEADER_LIST_SIZE", Flags.defaultHttp2MaxHeaderListSize()); - - /** - * The maximum length of an HTTP/1 response initial line. - */ - public static final ClientFactoryOption HTTP1_MAX_INITIAL_LINE_LENGTH = - ClientFactoryOption.define("HTTP1_MAX_INITIAL_LINE_LENGTH", - Flags.defaultHttp1MaxInitialLineLength()); - - /** - * The maximum length of all headers in an HTTP/1 response. - */ - public static final ClientFactoryOption HTTP1_MAX_HEADER_SIZE = - ClientFactoryOption.define("HTTP1_MAX_HEADER_SIZE", Flags.defaultHttp1MaxHeaderSize()); - - /** - * The maximum length of each chunk in an HTTP/1 response content. - */ - public static final ClientFactoryOption HTTP1_MAX_CHUNK_SIZE = - ClientFactoryOption.define("HTTP1_MAX_CHUNK_SIZE", Flags.defaultHttp1MaxChunkSize()); - - /** - * The idle timeout of a socket connection in milliseconds. - */ - public static final ClientFactoryOption IDLE_TIMEOUT_MILLIS = - ClientFactoryOption.define("IDLE_TIMEOUT_MILLIS", Flags.defaultClientIdleTimeoutMillis()); - - /** - * If the idle timeout is reset when an HTTP/2 PING frame or the response of {@code "OPTIONS * HTTP/1.1"} - * is received. - */ - @UnstableApi - public static final ClientFactoryOption KEEP_ALIVE_ON_PING = - ClientFactoryOption.define("KEEP_ALIVE_ON_PING", Flags.defaultClientKeepAliveOnPing()); - - /** - * The PING interval in milliseconds. - * When neither read nor write was performed for the specified period of time, - * a PING frame is sent for HTTP/2 - * or an OPTIONS request with - * an asterisk ("*") is sent for HTTP/1. - */ - public static final ClientFactoryOption PING_INTERVAL_MILLIS = - ClientFactoryOption.define("PING_INTERVAL_MILLIS", Flags.defaultPingIntervalMillis()); - - /** - * The client-side max age of a connection for keep-alive in milliseconds. - * If the value is greater than {@code 0}, a connection is disconnected after the specified - * amount of time since the connection was established. - * This option is disabled by default, which means unlimited. - */ - public static final ClientFactoryOption MAX_CONNECTION_AGE_MILLIS = - ClientFactoryOption.define("MAX_CONNECTION_AGE_MILLIS", clampedDefaultMaxClientConnectionAge()); - - private static long clampedDefaultMaxClientConnectionAge() { - final long connectionAgeMillis = Flags.defaultMaxClientConnectionAgeMillis(); - if (connectionAgeMillis > 0 && connectionAgeMillis < MIN_MAX_CONNECTION_AGE_MILLIS) { - return MIN_MAX_CONNECTION_AGE_MILLIS; + extends AbstractOptions, ClientFactoryOptionValue> { + + /** + * The worker {@link EventLoopGroup}. + */ + public static final ClientFactoryOption WORKER_GROUP = ClientFactoryOption.define("WORKER_GROUP", + CommonPools.workerGroup()); + + /** + * Whether to shut down the worker {@link EventLoopGroup} when the + * {@link ClientFactory} is closed. + */ + public static final ClientFactoryOption SHUTDOWN_WORKER_GROUP_ON_CLOSE = ClientFactoryOption + .define("SHUTDOWN_WORKER_GROUP_ON_CLOSE", false); + + /** + * The factory that creates an {@link EventLoopScheduler} which is responsible + * for assigning an + * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. + * @deprecated This factory method lacks the ability to build a sophisticated scheduler. + * Use the Custom_EVENT_LOOP_SCHEDULER_FACTORY instead. + */ + @Deprecated + public static final ClientFactoryOption> EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption + .define( + "EVENT_LOOP_SCHEDULER_FACTORY", + eventLoopGroup -> new DefaultEventLoopScheduler(eventLoopGroup, 0, 0, ImmutableList.of())); + + /** + * The factory that creates an {@link EventLoopScheduler} which is responsible + * for assigning an + * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. + */ + public static final ClientFactoryOption CUSTOM_EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption + .define("EVENT_LOOP_SCHEDULER_FACTORY", + (eventLoopGroup, + maxNumEventLoopFunctions, + maxNumEventLoopsPerEndpoint, + maxNumEventLoopsPerHttp1Endpoint, + idleTimeOutMillis) -> { + return new DefaultEventLoopScheduler(eventLoopGroup, + maxNumEventLoopsPerEndpoint, + maxNumEventLoopsPerHttp1Endpoint, + maxNumEventLoopFunctions); + }); + + /** + * The {@link Consumer} which can arbitrarily configure the + * {@link SslContextBuilder} that will be + * applied to the SSL session. + */ + public static final ClientFactoryOption> TLS_CUSTOMIZER = ClientFactoryOption + .define("TLS_CUSTOMIZER", b -> { + /* no-op */ }); + + /** + * Whether to allow the bad cipher suites listed in + * RFC7540 for + * TLS handshake. + * + *

+ * Note that enabling this option increases the security risk of your + * connection. + * Use it only when you must communicate with a legacy system that does not + * support + * secure cipher suites. + * See + * Section + * 9.2.2, RFC7540 for + * more information. + * + * @deprecated It's not recommended to enable this option. Use it only when you + * have no other way to + * communicate with an insecure peer than this. + */ + @Deprecated + public static final ClientFactoryOption TLS_ALLOW_UNSAFE_CIPHERS = ClientFactoryOption + .define("tlsAllowUnsafeCiphers", Flags.tlsAllowUnsafeCiphers()); + + /** + * The factory that creates an {@link AddressResolverGroup} which resolves + * remote addresses into + * {@link InetSocketAddress}es. + */ + public static final ClientFactoryOption>> ADDRESS_RESOLVER_GROUP_FACTORY = ClientFactoryOption + .define("ADDRESS_RESOLVER_GROUP_FACTORY", + eventLoopGroup -> new DnsResolverGroupBuilder().build(eventLoopGroup)); + + /** + * The HTTP/2 + * initial + * connection flow-control + * window size. + */ + public static final ClientFactoryOption HTTP2_INITIAL_CONNECTION_WINDOW_SIZE = ClientFactoryOption.define( + "HTTP2_INITIAL_CONNECTION_WINDOW_SIZE", + Flags.defaultHttp2InitialConnectionWindowSize()); + + /** + * The SETTINGS_INITIAL_WINDOW_SIZE + * for HTTP/2 stream-level flow control. + */ + public static final ClientFactoryOption HTTP2_INITIAL_STREAM_WINDOW_SIZE = ClientFactoryOption.define( + "HTTP2_INITIAL_STREAM_WINDOW_SIZE", + Flags.defaultHttp2InitialStreamWindowSize()); + + /** + * The SETTINGS_MAX_FRAME_SIZE + * that indicates the size of the largest frame payload that this client is + * willing to receive. + */ + public static final ClientFactoryOption HTTP2_MAX_FRAME_SIZE = ClientFactoryOption + .define("HTTP2_MAX_FRAME_SIZE", Flags.defaultHttp2MaxFrameSize()); + + /** + * The HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE + * that indicates the maximum size of header list that the client is prepared to + * accept, in octets. + */ + public static final ClientFactoryOption HTTP2_MAX_HEADER_LIST_SIZE = ClientFactoryOption + .define("HTTP2_MAX_HEADER_LIST_SIZE", Flags.defaultHttp2MaxHeaderListSize()); + + /** + * The maximum length of an HTTP/1 response initial line. + */ + public static final ClientFactoryOption HTTP1_MAX_INITIAL_LINE_LENGTH = ClientFactoryOption.define( + "HTTP1_MAX_INITIAL_LINE_LENGTH", + Flags.defaultHttp1MaxInitialLineLength()); + + /** + * The maximum length of all headers in an HTTP/1 response. + */ + public static final ClientFactoryOption HTTP1_MAX_HEADER_SIZE = ClientFactoryOption + .define("HTTP1_MAX_HEADER_SIZE", Flags.defaultHttp1MaxHeaderSize()); + + /** + * The maximum length of each chunk in an HTTP/1 response content. + */ + public static final ClientFactoryOption HTTP1_MAX_CHUNK_SIZE = ClientFactoryOption + .define("HTTP1_MAX_CHUNK_SIZE", Flags.defaultHttp1MaxChunkSize()); + + /** + * The idle timeout of a socket connection in milliseconds. + */ + public static final ClientFactoryOption IDLE_TIMEOUT_MILLIS = ClientFactoryOption.define("IDLE_TIMEOUT_MILLIS", + Flags.defaultClientIdleTimeoutMillis()); + + /** + * If the idle timeout is reset when an HTTP/2 PING frame or the response of + * {@code "OPTIONS * HTTP/1.1"} + * is received. + */ + @UnstableApi + public static final ClientFactoryOption KEEP_ALIVE_ON_PING = ClientFactoryOption.define("KEEP_ALIVE_ON_PING", + Flags.defaultClientKeepAliveOnPing()); + + /** + * The PING interval in milliseconds. + * When neither read nor write was performed for the specified period of time, + * a + * PING + * frame is sent for HTTP/2 + * or an OPTIONS + * request with + * an asterisk ("*") is sent for HTTP/1. + */ + public static final ClientFactoryOption PING_INTERVAL_MILLIS = ClientFactoryOption + .define("PING_INTERVAL_MILLIS", Flags.defaultPingIntervalMillis()); + + /** + * The client-side max age of a connection for keep-alive in milliseconds. + * If the value is greater than {@code 0}, a connection is disconnected after + * the specified + * amount of time since the connection was established. + * This option is disabled by default, which means unlimited. + */ + public static final ClientFactoryOption MAX_CONNECTION_AGE_MILLIS = ClientFactoryOption + .define("MAX_CONNECTION_AGE_MILLIS", clampedDefaultMaxClientConnectionAge()); + + private static long clampedDefaultMaxClientConnectionAge() { + final long connectionAgeMillis = Flags.defaultMaxClientConnectionAgeMillis(); + if (connectionAgeMillis > 0 && connectionAgeMillis < MIN_MAX_CONNECTION_AGE_MILLIS) { + return MIN_MAX_CONNECTION_AGE_MILLIS; + } + return connectionAgeMillis; + } + + /** + * The client-side maximum allowed number of requests that can be sent through + * one connection. + * This option is disabled by default, which means unlimited. + */ + public static final ClientFactoryOption MAX_NUM_REQUESTS_PER_CONNECTION = ClientFactoryOption.define( + "MAX_NUM_REQUESTS_PER_CONNECTION", + Flags.defaultMaxClientNumRequestsPerConnection()); + + /** + * Whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request + * to negotiate + * the protocol version of a cleartext HTTP connection. + */ + public static final ClientFactoryOption USE_HTTP2_PREFACE = ClientFactoryOption.define("USE_HTTP2_PREFACE", + Flags.defaultUseHttp2Preface()); + + /** + * Whether to use HTTP/1.1 instead of HTTP/2. If enabled, the client will not + * attempt to upgrade to + * HTTP/2 for {@link SessionProtocol#HTTP} and {@link SessionProtocol#HTTPS}. + */ + @UnstableApi + public static final ClientFactoryOption PREFER_HTTP1 = ClientFactoryOption.define("PREFER_HTTP1", + Flags.defaultPreferHttp1()); + + /** + * Whether to use HTTP/2 without ALPN. This is useful if you want to communicate + * with an HTTP/2 + * server over TLS but the server does not support ALPN. + */ + @UnstableApi + public static final ClientFactoryOption USE_HTTP2_WITHOUT_ALPN = ClientFactoryOption + .define("USE_HTTP2_WITHOUT_ALPN", Flags.defaultUseHttp2WithoutAlpn()); + + /** + * Whether to use HTTP + * pipelining for + * HTTP/1 connections. + */ + public static final ClientFactoryOption USE_HTTP1_PIPELINING = ClientFactoryOption + .define("USE_HTTP1_PIPELINING", Flags.defaultUseHttp1Pipelining()); + + /** + * The listener which is notified on a connection pool event. + */ + public static final ClientFactoryOption CONNECTION_POOL_LISTENER = ClientFactoryOption + .define("CONNECTION_POOL_LISTENER", ConnectionPoolListener.noop()); + + /** + * The {@link MeterRegistry} which collects various stats. + */ + public static final ClientFactoryOption METER_REGISTRY = ClientFactoryOption.define("METER_REGISTRY", + Flags.meterRegistry()); + + /** + * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to + * be used. + */ + public static final ClientFactoryOption PROXY_CONFIG_SELECTOR = ClientFactoryOption + .define("PROXY_CONFIG_SELECTOR", ProxyConfigSelector.of(ProxyConfig.direct())); + + /** + * The {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name + * into + * another HTTP/1 header name. + */ + public static final ClientFactoryOption HTTP1_HEADER_NAMING = ClientFactoryOption + .define("HTTP1_HEADER_NAMING", Http1HeaderNaming.ofDefault()); + + /** + * The {@link ChannelOption}s of the sockets created by the + * {@link ClientFactory}. + */ + public static final ClientFactoryOption, Object>> CHANNEL_OPTIONS = ClientFactoryOption + .define("CHANNEL_OPTIONS", ImmutableMap.of(), newOptions -> { + for (ChannelOption channelOption : ChannelUtil.prohibitedOptions()) { + checkArgument(!newOptions.containsKey(channelOption), + "prohibited channel option: %s", channelOption); } - return connectionAgeMillis; - } - - /** - * The client-side maximum allowed number of requests that can be sent through one connection. - * This option is disabled by default, which means unlimited. - */ - public static final ClientFactoryOption MAX_NUM_REQUESTS_PER_CONNECTION = - ClientFactoryOption.define("MAX_NUM_REQUESTS_PER_CONNECTION", - Flags.defaultMaxClientNumRequestsPerConnection()); - - /** - * Whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request to negotiate - * the protocol version of a cleartext HTTP connection. - */ - public static final ClientFactoryOption USE_HTTP2_PREFACE = - ClientFactoryOption.define("USE_HTTP2_PREFACE", Flags.defaultUseHttp2Preface()); - - /** - * Whether to use HTTP/1.1 instead of HTTP/2. If enabled, the client will not attempt to upgrade to - * HTTP/2 for {@link SessionProtocol#HTTP} and {@link SessionProtocol#HTTPS}. - */ - @UnstableApi - public static final ClientFactoryOption PREFER_HTTP1 = - ClientFactoryOption.define("PREFER_HTTP1", Flags.defaultPreferHttp1()); - - /** - * Whether to use HTTP/2 without ALPN. This is useful if you want to communicate with an HTTP/2 - * server over TLS but the server does not support ALPN. - */ - @UnstableApi - public static final ClientFactoryOption USE_HTTP2_WITHOUT_ALPN = - ClientFactoryOption.define("USE_HTTP2_WITHOUT_ALPN", Flags.defaultUseHttp2WithoutAlpn()); - - /** - * Whether to use HTTP pipelining for - * HTTP/1 connections. - */ - public static final ClientFactoryOption USE_HTTP1_PIPELINING = - ClientFactoryOption.define("USE_HTTP1_PIPELINING", Flags.defaultUseHttp1Pipelining()); - - /** - * The listener which is notified on a connection pool event. - */ - public static final ClientFactoryOption CONNECTION_POOL_LISTENER = - ClientFactoryOption.define("CONNECTION_POOL_LISTENER", ConnectionPoolListener.noop()); - - /** - * The {@link MeterRegistry} which collects various stats. - */ - public static final ClientFactoryOption METER_REGISTRY = - ClientFactoryOption.define("METER_REGISTRY", Flags.meterRegistry()); - - /** - * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to be used. - */ - public static final ClientFactoryOption PROXY_CONFIG_SELECTOR = - ClientFactoryOption.define("PROXY_CONFIG_SELECTOR", ProxyConfigSelector.of(ProxyConfig.direct())); - - /** - * The {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name into - * another HTTP/1 header name. - */ - public static final ClientFactoryOption HTTP1_HEADER_NAMING = - ClientFactoryOption.define("HTTP1_HEADER_NAMING", Http1HeaderNaming.ofDefault()); - - /** - * The {@link ChannelOption}s of the sockets created by the {@link ClientFactory}. - */ - public static final ClientFactoryOption, Object>> CHANNEL_OPTIONS = - ClientFactoryOption.define("CHANNEL_OPTIONS", ImmutableMap.of(), newOptions -> { - for (ChannelOption channelOption : ChannelUtil.prohibitedOptions()) { - checkArgument(!newOptions.containsKey(channelOption), - "prohibited channel option: %s", channelOption); - } - return newOptions; - }, (oldValue, newValue) -> { - final Map, Object> newOptions = newValue.value(); - if (newOptions.isEmpty()) { - return oldValue; - } - final Map, Object> oldOptions = oldValue.value(); - if (oldOptions.isEmpty()) { - return newValue; - } - final ImmutableMap.Builder, Object> builder = - ImmutableMap.builderWithExpectedSize(oldOptions.size() + newOptions.size()); - oldOptions.forEach((key, value) -> { - if (!newOptions.containsKey(key)) { - builder.put(key, value); - } - }); - builder.putAll(newOptions); - return newValue.option().newValue(builder.build()); - }); - - /** - * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. - * This customizer is run right before {@link ChannelPipeline#connect(SocketAddress)} - * is invoked by Armeria. This customizer is no-op by default. - * - *

Note that usage of this customizer is an advanced - * feature and may produce unintended side effects, including complete - * breakdown. It is not recommended if you are not familiar with - * Armeria and Netty internals. - */ - @UnstableApi - public static final ClientFactoryOption> CHANNEL_PIPELINE_CUSTOMIZER = - ClientFactoryOption.define("CHANNEL_PIPELINE_CUSTOMIZER", v -> { /* no-op */ }); - - private static final ClientFactoryOptions EMPTY = new ClientFactoryOptions(ImmutableList.of()); - - /** - * Returns an empty singleton {@link ClientFactoryOptions}. - */ - public static ClientFactoryOptions of() { - return EMPTY; - } - - /** - * Returns the {@link ClientFactoryOptions} with the specified {@link ClientFactoryOptionValue}s. - */ - public static ClientFactoryOptions of(ClientFactoryOptionValue... values) { - requireNonNull(values, "values"); - if (values.length == 0) { - return EMPTY; - } - return of(Arrays.asList(values)); - } - - /** - * Returns the {@link ClientFactoryOptions} with the specified {@link ClientFactoryOptionValue}s. - */ - public static ClientFactoryOptions of(Iterable> values) { - requireNonNull(values, "values"); - if (values instanceof ClientFactoryOptions) { - return (ClientFactoryOptions) values; + return newOptions; + }, (oldValue, newValue) -> { + final Map, Object> newOptions = newValue.value(); + if (newOptions.isEmpty()) { + return oldValue; } - return new ClientFactoryOptions(values); - } - - /** - * Merges the specified {@link ClientFactoryOptions} and {@link ClientFactoryOptionValue}s. - * - * @return the merged {@link ClientFactoryOptions} - */ - public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, - ClientFactoryOptionValue... additionalValues) { - requireNonNull(baseOptions, "baseOptions"); - requireNonNull(additionalValues, "additionalValues"); - if (additionalValues.length == 0) { - return baseOptions; + final Map, Object> oldOptions = oldValue.value(); + if (oldOptions.isEmpty()) { + return newValue; } - return new ClientFactoryOptions(baseOptions, Arrays.asList(additionalValues)); - } - - /** - * Merges the specified {@link ClientFactoryOptions} and {@link ClientFactoryOptionValue}s. - * - * @return the merged {@link ClientFactoryOptions} - */ - public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, - Iterable> additionalValues) { - requireNonNull(baseOptions, "baseOptions"); - requireNonNull(additionalValues, "additionalValues"); - return new ClientFactoryOptions(baseOptions, additionalValues); - } - - private ClientFactoryOptions(Iterable> values) { - super(values); - } - - private ClientFactoryOptions(ClientFactoryOptions baseOptions, - Iterable> additionalValues) { - - super(baseOptions, additionalValues); - } - - /** - * Returns the worker {@link EventLoopGroup}. - */ - public EventLoopGroup workerGroup() { - return get(WORKER_GROUP); - } - - /** - * Returns the flag whether to shut down the worker {@link EventLoopGroup} - * when the {@link ClientFactory} is closed. - */ - public boolean shutdownWorkerGroupOnClose() { - return get(SHUTDOWN_WORKER_GROUP_ON_CLOSE); - } - - /** - * Returns the factory that creates an {@link EventLoopScheduler} which is responsible for assigning an - * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. - */ - public Function eventLoopSchedulerFactory() { - return get(EVENT_LOOP_SCHEDULER_FACTORY); - } - - /** - * Returns the {@link ChannelOption}s of the sockets created by the {@link ClientFactory}. - */ - public Map, Object> channelOptions() { - return get(CHANNEL_OPTIONS); - } - - /** - * Returns the {@link Consumer} which can arbitrarily configure the {@link SslContextBuilder} that will be - * applied to the SSL session. - */ - public Consumer tlsCustomizer() { - return get(TLS_CUSTOMIZER); - } - - /** - * Returns the factory that creates an {@link AddressResolverGroup} which resolves remote addresses into - * {@link InetSocketAddress}es. - */ - public Function> addressResolverGroupFactory() { - - return get(ADDRESS_RESOLVER_GROUP_FACTORY); - } - - /** - * Returns the HTTP/2 initial connection - * flow-control window size. - */ - public int http2InitialConnectionWindowSize() { - return get(HTTP2_INITIAL_CONNECTION_WINDOW_SIZE); - } - - /** - * Returns the SETTINGS_INITIAL_WINDOW_SIZE - * for HTTP/2 stream-level flow control. - */ - public int http2InitialStreamWindowSize() { - return get(HTTP2_INITIAL_STREAM_WINDOW_SIZE); - } - - /** - * Returns the SETTINGS_MAX_FRAME_SIZE - * that indicates the size of the largest frame payload that this client is willing to receive. - */ - public int http2MaxFrameSize() { - return get(HTTP2_MAX_FRAME_SIZE); - } - - /** - * Returns the HTTP/2 - * SETTINGS_MAX_HEADER_LIST_SIZE that indicates the maximum size of header list - * that the client is prepared to accept, in octets. - */ - public long http2MaxHeaderListSize() { - return get(HTTP2_MAX_HEADER_LIST_SIZE); - } - - /** - * Returns the maximum length of an HTTP/1 response initial line. - */ - public int http1MaxInitialLineLength() { - return get(HTTP1_MAX_INITIAL_LINE_LENGTH); - } - - /** - * Returns the maximum length of all headers in an HTTP/1 response. - */ - public int http1MaxHeaderSize() { - return get(HTTP1_MAX_HEADER_SIZE); - } - - /** - * Returns the maximum length of each chunk in an HTTP/1 response content. - */ - public int http1MaxChunkSize() { - return get(HTTP1_MAX_CHUNK_SIZE); - } - - /** - * Returns the idle timeout of a socket connection in milliseconds. - */ - public long idleTimeoutMillis() { - return get(IDLE_TIMEOUT_MILLIS); - } - - /** - * Returns whether to keep connection alive when an HTTP/2 PING frame or the response of - * {@code "OPTIONS * HTTP/1.1"} is received. - */ - @UnstableApi - public boolean keepAliveOnPing() { - return get(KEEP_ALIVE_ON_PING); - } - - /** - * Returns the PING interval in milliseconds. - * When neither read nor write was performed for the specified period of time, - * a PING frame is sent for HTTP/2 - * or an OPTIONS request with - * an asterisk ("*") is sent for HTTP/1. - */ - public long pingIntervalMillis() { - return get(PING_INTERVAL_MILLIS); - } - - /** - * Returns the client-side max age of a connection for keep-alive in milliseconds. - * If the value is greater than {@code 0}, a connection is disconnected after the specified - * amount of the time since the connection was established. - */ - public long maxConnectionAgeMillis() { - return get(MAX_CONNECTION_AGE_MILLIS); - } - - /** - * Returns the client-side maximum allowed number of requests that can be sent through one connection. - */ - public int maxNumRequestsPerConnection() { - return get(MAX_NUM_REQUESTS_PER_CONNECTION); - } - - /** - * Returns whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request to negotiate - * the protocol version of a cleartext HTTP connection. - */ - public boolean useHttp2Preface() { - return get(USE_HTTP2_PREFACE); - } - - /** - * Returns whether to use HTTP/1.1 instead of HTTP/2 . If {@code true}, the client will not attempt to - * upgrade to HTTP/2 for {@link SessionProtocol#HTTP} and {@link SessionProtocol#HTTPS}. - */ - @UnstableApi - public boolean preferHttp1() { - return get(PREFER_HTTP1); - } - - /** - * Returns whether to use HTTP/2 over TLS without ALPN. - */ - @UnstableApi - public boolean useHttp2WithoutAlpn() { - return get(USE_HTTP2_WITHOUT_ALPN); - } - - /** - * Returns whether to use HTTP pipelining for - * HTTP/1 connections. - */ - public boolean useHttp1Pipelining() { - return get(USE_HTTP1_PIPELINING); - } - - /** - * Returns the listener which is notified on a connection pool event. - */ - public ConnectionPoolListener connectionPoolListener() { - return get(CONNECTION_POOL_LISTENER); - } - - /** - * Returns the {@link MeterRegistry} which collects various stats. - */ - public MeterRegistry meterRegistry() { - return get(METER_REGISTRY); - } - - /** - * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to be used. - */ - public ProxyConfigSelector proxyConfigSelector() { - return get(PROXY_CONFIG_SELECTOR); - } - - /** - * Returns the {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name into - * another header name. This is useful when communicating with a legacy system that only supports - * case-sensitive HTTP/1 headers. - */ - public Http1HeaderNaming http1HeaderNaming() { - return get(HTTP1_HEADER_NAMING); - } - - /** - * Returns whether to allow the bad cipher suites listed in - * RFC7540 for TLS handshake. - * - *

Note that enabling this option increases the security risk of your connection. - * Use it only when you must communicate with a legacy system that does not support - * secure cipher suites. - * See Section 9.2.2, RFC7540 for - * more information. - */ - public boolean tlsAllowUnsafeCiphers() { - return get(TLS_ALLOW_UNSAFE_CIPHERS); - } - - /** - * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. - * This customizer is run right before {@link ChannelPipeline#connect(SocketAddress)} - * is invoked by Armeria. This customizer is no-op by default. - * - *

Note that usage of this customizer is an advanced - * feature and may produce unintended side effects, including complete - * breakdown. It is not recommended if you are not familiar with - * Armeria and Netty internals. - */ - @UnstableApi - public Consumer channelPipelineCustomizer() { - return get(CHANNEL_PIPELINE_CUSTOMIZER); - } + final ImmutableMap.Builder, Object> builder = ImmutableMap + .builderWithExpectedSize(oldOptions.size() + newOptions.size()); + oldOptions.forEach((key, value) -> { + if (!newOptions.containsKey(key)) { + builder.put(key, value); + } + }); + builder.putAll(newOptions); + return newValue.option().newValue(builder.build()); + }); + + /** + * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. + * This customizer is run right before + * {@link ChannelPipeline#connect(SocketAddress)} + * is invoked by Armeria. This customizer is no-op by default. + * + *

+ * Note that usage of this customizer is an advanced + * feature and may produce unintended side effects, including complete + * breakdown. It is not recommended if you are not familiar with + * Armeria and Netty internals. + */ + @UnstableApi + public static final ClientFactoryOption> CHANNEL_PIPELINE_CUSTOMIZER = ClientFactoryOption + .define("CHANNEL_PIPELINE_CUSTOMIZER", v -> { + /* no-op */ }); + + private static final ClientFactoryOptions EMPTY = new ClientFactoryOptions(ImmutableList.of()); + + /** + * Returns an empty singleton {@link ClientFactoryOptions}. + */ + public static ClientFactoryOptions of() { + return EMPTY; + } + + /** + * Returns the {@link ClientFactoryOptions} with the specified + * {@link ClientFactoryOptionValue}s. + */ + public static ClientFactoryOptions of(ClientFactoryOptionValue... values) { + requireNonNull(values, "values"); + if (values.length == 0) { + return EMPTY; + } + return of(Arrays.asList(values)); + } + + /** + * Returns the {@link ClientFactoryOptions} with the specified + * {@link ClientFactoryOptionValue}s. + */ + public static ClientFactoryOptions of(Iterable> values) { + requireNonNull(values, "values"); + if (values instanceof ClientFactoryOptions) { + return (ClientFactoryOptions) values; + } + return new ClientFactoryOptions(values); + } + + /** + * Merges the specified {@link ClientFactoryOptions} and + * {@link ClientFactoryOptionValue}s. + * + * @return the merged {@link ClientFactoryOptions} + */ + public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, + ClientFactoryOptionValue... additionalValues) { + requireNonNull(baseOptions, "baseOptions"); + requireNonNull(additionalValues, "additionalValues"); + if (additionalValues.length == 0) { + return baseOptions; + } + return new ClientFactoryOptions(baseOptions, Arrays.asList(additionalValues)); + } + + /** + * Merges the specified {@link ClientFactoryOptions} and + * {@link ClientFactoryOptionValue}s. + * + * @return the merged {@link ClientFactoryOptions} + */ + public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, + Iterable> additionalValues) { + requireNonNull(baseOptions, "baseOptions"); + requireNonNull(additionalValues, "additionalValues"); + return new ClientFactoryOptions(baseOptions, additionalValues); + } + + private ClientFactoryOptions(Iterable> values) { + super(values); + } + + private ClientFactoryOptions(ClientFactoryOptions baseOptions, + Iterable> additionalValues) { + + super(baseOptions, additionalValues); + } + + /** + * Returns the worker {@link EventLoopGroup}. + */ + public EventLoopGroup workerGroup() { + return get(WORKER_GROUP); + } + + /** + * Returns the flag whether to shut down the worker {@link EventLoopGroup} + * when the {@link ClientFactory} is closed. + */ + public boolean shutdownWorkerGroupOnClose() { + return get(SHUTDOWN_WORKER_GROUP_ON_CLOSE); + } + + /** + * Returns the factory that creates an {@link EventLoopScheduler} which is + * responsible for assigning an + * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. + */ + public Function eventLoopSchedulerFactory() { + return get(EVENT_LOOP_SCHEDULER_FACTORY); + } + + /** + * Returns the {@link ChannelOption}s of the sockets created by the + * {@link ClientFactory}. + */ + public Map, Object> channelOptions() { + return get(CHANNEL_OPTIONS); + } + + /** + * Returns the {@link Consumer} which can arbitrarily configure the + * {@link SslContextBuilder} that will be + * applied to the SSL session. + */ + public Consumer tlsCustomizer() { + return get(TLS_CUSTOMIZER); + } + + /** + * Returns the factory that creates an {@link AddressResolverGroup} which + * resolves remote addresses into + * {@link InetSocketAddress}es. + */ + public Function> addressResolverGroupFactory() { + + return get(ADDRESS_RESOLVER_GROUP_FACTORY); + } + + /** + * Returns the HTTP/2 + * initial + * connection + * flow-control window size. + */ + public int http2InitialConnectionWindowSize() { + return get(HTTP2_INITIAL_CONNECTION_WINDOW_SIZE); + } + + /** + * Returns the SETTINGS_INITIAL_WINDOW_SIZE + * for HTTP/2 stream-level flow control. + */ + public int http2InitialStreamWindowSize() { + return get(HTTP2_INITIAL_STREAM_WINDOW_SIZE); + } + + /** + * Returns the SETTINGS_MAX_FRAME_SIZE + * that indicates the size of the largest frame payload that this client is + * willing to receive. + */ + public int http2MaxFrameSize() { + return get(HTTP2_MAX_FRAME_SIZE); + } + + /** + * Returns the HTTP/2 + * + * SETTINGS_MAX_HEADER_LIST_SIZE that indicates the maximum size of header + * list + * that the client is prepared to accept, in octets. + */ + public long http2MaxHeaderListSize() { + return get(HTTP2_MAX_HEADER_LIST_SIZE); + } + + /** + * Returns the maximum length of an HTTP/1 response initial line. + */ + public int http1MaxInitialLineLength() { + return get(HTTP1_MAX_INITIAL_LINE_LENGTH); + } + + /** + * Returns the maximum length of all headers in an HTTP/1 response. + */ + public int http1MaxHeaderSize() { + return get(HTTP1_MAX_HEADER_SIZE); + } + + /** + * Returns the maximum length of each chunk in an HTTP/1 response content. + */ + public int http1MaxChunkSize() { + return get(HTTP1_MAX_CHUNK_SIZE); + } + + /** + * Returns the idle timeout of a socket connection in milliseconds. + */ + public long idleTimeoutMillis() { + return get(IDLE_TIMEOUT_MILLIS); + } + + /** + * Returns whether to keep connection alive when an HTTP/2 PING frame or the + * response of + * {@code "OPTIONS * HTTP/1.1"} is received. + */ + @UnstableApi + public boolean keepAliveOnPing() { + return get(KEEP_ALIVE_ON_PING); + } + + /** + * Returns the PING interval in milliseconds. + * When neither read nor write was performed for the specified period of time, + * a + * PING + * frame is sent for HTTP/2 + * or an OPTIONS + * request with + * an asterisk ("*") is sent for HTTP/1. + */ + public long pingIntervalMillis() { + return get(PING_INTERVAL_MILLIS); + } + + /** + * Returns the client-side max age of a connection for keep-alive in + * milliseconds. + * If the value is greater than {@code 0}, a connection is disconnected after + * the specified + * amount of the time since the connection was established. + */ + public long maxConnectionAgeMillis() { + return get(MAX_CONNECTION_AGE_MILLIS); + } + + /** + * Returns the client-side maximum allowed number of requests that can be sent + * through one connection. + */ + public int maxNumRequestsPerConnection() { + return get(MAX_NUM_REQUESTS_PER_CONNECTION); + } + + /** + * Returns whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade + * request to negotiate + * the protocol version of a cleartext HTTP connection. + */ + public boolean useHttp2Preface() { + return get(USE_HTTP2_PREFACE); + } + + /** + * Returns whether to use HTTP/1.1 instead of HTTP/2 . If {@code true}, the + * client will not attempt to + * upgrade to HTTP/2 for {@link SessionProtocol#HTTP} and + * {@link SessionProtocol#HTTPS}. + */ + @UnstableApi + public boolean preferHttp1() { + return get(PREFER_HTTP1); + } + + /** + * Returns whether to use HTTP/2 over TLS without ALPN. + */ + @UnstableApi + public boolean useHttp2WithoutAlpn() { + return get(USE_HTTP2_WITHOUT_ALPN); + } + + /** + * Returns whether to use + * HTTP pipelining + * for + * HTTP/1 connections. + */ + public boolean useHttp1Pipelining() { + return get(USE_HTTP1_PIPELINING); + } + + /** + * Returns the listener which is notified on a connection pool event. + */ + public ConnectionPoolListener connectionPoolListener() { + return get(CONNECTION_POOL_LISTENER); + } + + /** + * Returns the {@link MeterRegistry} which collects various stats. + */ + public MeterRegistry meterRegistry() { + return get(METER_REGISTRY); + } + + /** + * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to + * be used. + */ + public ProxyConfigSelector proxyConfigSelector() { + return get(PROXY_CONFIG_SELECTOR); + } + + /** + * Returns the {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 + * header name into + * another header name. This is useful when communicating with a legacy system + * that only supports + * case-sensitive HTTP/1 headers. + */ + public Http1HeaderNaming http1HeaderNaming() { + return get(HTTP1_HEADER_NAMING); + } + + /** + * Returns whether to allow the bad cipher suites listed in + * RFC7540 for + * TLS handshake. + * + *

+ * Note that enabling this option increases the security risk of your + * connection. + * Use it only when you must communicate with a legacy system that does not + * support + * secure cipher suites. + * See + * Section + * 9.2.2, RFC7540 for + * more information. + */ + public boolean tlsAllowUnsafeCiphers() { + return get(TLS_ALLOW_UNSAFE_CIPHERS); + } + + /** + * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. + * This customizer is run right before + * {@link ChannelPipeline#connect(SocketAddress)} + * is invoked by Armeria. This customizer is no-op by default. + * + *

+ * Note that usage of this customizer is an advanced + * feature and may produce unintended side effects, including complete + * breakdown. It is not recommended if you are not familiar with + * Armeria and Netty internals. + */ + @UnstableApi + public Consumer channelPipelineCustomizer() { + return get(CHANNEL_PIPELINE_CUSTOMIZER); + } } diff --git a/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java b/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java new file mode 100644 index 00000000000..bab6458ef66 --- /dev/null +++ b/core/src/main/java/com/linecorp/armeria/client/EventLoopSchedulerFactory.java @@ -0,0 +1,15 @@ +package com.linecorp.armeria.client; + +import io.netty.channel.EventLoopGroup; + +import java.util.List; +import java.util.function.ToIntFunction; + +@FunctionalInterface +public interface EventLoopSchedulerFactory { + EventLoopScheduler newScheduler(EventLoopGroup eventLoopGroup, + List> maxNumEventLoopFunctions, + int maxNumEventLoopsPerEndpoint, + int maxNumEventLoopsPerHttp1Endpoint, + long idleTimeOutMillis); +} From af2f9d01fc0dc58042468efb353e6d35c646a0f8 Mon Sep 17 00:00:00 2001 From: Layla Silbernberg <119636966+LaylaSilbernberg@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:11:14 +0100 Subject: [PATCH 3/3] further cleanup --- .../armeria/client/ClientFactoryOptions.java | 413 +++++++----------- 1 file changed, 170 insertions(+), 243 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java index 03de20e1766..e9619e614e6 100644 --- a/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java +++ b/core/src/main/java/com/linecorp/armeria/client/ClientFactoryOptions.java @@ -1,3 +1,4 @@ + /* * Copyright 2019 LINE Corporation * @@ -51,20 +52,19 @@ * A set of {@link ClientFactoryOption}s and their respective values. */ public final class ClientFactoryOptions - extends AbstractOptions, ClientFactoryOptionValue> { + extends AbstractOptions, ClientFactoryOptionValue> { /** * The worker {@link EventLoopGroup}. */ - public static final ClientFactoryOption WORKER_GROUP = ClientFactoryOption.define("WORKER_GROUP", - CommonPools.workerGroup()); + public static final ClientFactoryOption WORKER_GROUP = + ClientFactoryOption.define("WORKER_GROUP", CommonPools.workerGroup()); /** - * Whether to shut down the worker {@link EventLoopGroup} when the - * {@link ClientFactory} is closed. + * Whether to shut down the worker {@link EventLoopGroup} when the {@link ClientFactory} is closed. */ - public static final ClientFactoryOption SHUTDOWN_WORKER_GROUP_ON_CLOSE = ClientFactoryOption - .define("SHUTDOWN_WORKER_GROUP_ON_CLOSE", false); + public static final ClientFactoryOption SHUTDOWN_WORKER_GROUP_ON_CLOSE = + ClientFactoryOption.define("SHUTDOWN_WORKER_GROUP_ON_CLOSE", false); /** * The factory that creates an {@link EventLoopScheduler} which is responsible @@ -74,8 +74,8 @@ public final class ClientFactoryOptions * Use the Custom_EVENT_LOOP_SCHEDULER_FACTORY instead. */ @Deprecated - public static final ClientFactoryOption> EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption - .define( + public static final ClientFactoryOption> + EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption.define( "EVENT_LOOP_SCHEDULER_FACTORY", eventLoopGroup -> new DefaultEventLoopScheduler(eventLoopGroup, 0, 0, ImmutableList.of())); @@ -85,155 +85,132 @@ public final class ClientFactoryOptions * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. */ public static final ClientFactoryOption CUSTOM_EVENT_LOOP_SCHEDULER_FACTORY = ClientFactoryOption - .define("EVENT_LOOP_SCHEDULER_FACTORY", - (eventLoopGroup, - maxNumEventLoopFunctions, - maxNumEventLoopsPerEndpoint, - maxNumEventLoopsPerHttp1Endpoint, - idleTimeOutMillis) -> { - return new DefaultEventLoopScheduler(eventLoopGroup, - maxNumEventLoopsPerEndpoint, - maxNumEventLoopsPerHttp1Endpoint, - maxNumEventLoopFunctions); - }); - - /** - * The {@link Consumer} which can arbitrarily configure the - * {@link SslContextBuilder} that will be + .define("EVENT_LOOP_SCHEDULER_FACTORY", + (eventLoopGroup, + maxNumEventLoopFunctions, + maxNumEventLoopsPerEndpoint, + maxNumEventLoopsPerHttp1Endpoint, + idleTimeOutMillis) -> { + return new DefaultEventLoopScheduler(eventLoopGroup, + maxNumEventLoopsPerEndpoint, + maxNumEventLoopsPerHttp1Endpoint, + maxNumEventLoopFunctions); + }); + + /** + * The {@link Consumer} which can arbitrarily configure the {@link SslContextBuilder} that will be * applied to the SSL session. */ - public static final ClientFactoryOption> TLS_CUSTOMIZER = ClientFactoryOption - .define("TLS_CUSTOMIZER", b -> { - /* no-op */ }); + public static final ClientFactoryOption> TLS_CUSTOMIZER = + ClientFactoryOption.define("TLS_CUSTOMIZER", b -> { /* no-op */ }); /** * Whether to allow the bad cipher suites listed in - * RFC7540 for - * TLS handshake. + * RFC7540 for TLS handshake. * - *

- * Note that enabling this option increases the security risk of your - * connection. - * Use it only when you must communicate with a legacy system that does not - * support + *

Note that enabling this option increases the security risk of your connection. + * Use it only when you must communicate with a legacy system that does not support * secure cipher suites. - * See - * Section - * 9.2.2, RFC7540 for + * See Section 9.2.2, RFC7540 for * more information. * - * @deprecated It's not recommended to enable this option. Use it only when you - * have no other way to + * @deprecated It's not recommended to enable this option. Use it only when you have no other way to * communicate with an insecure peer than this. */ @Deprecated - public static final ClientFactoryOption TLS_ALLOW_UNSAFE_CIPHERS = ClientFactoryOption - .define("tlsAllowUnsafeCiphers", Flags.tlsAllowUnsafeCiphers()); + public static final ClientFactoryOption TLS_ALLOW_UNSAFE_CIPHERS = + ClientFactoryOption.define("tlsAllowUnsafeCiphers", Flags.tlsAllowUnsafeCiphers()); /** - * The factory that creates an {@link AddressResolverGroup} which resolves - * remote addresses into + * The factory that creates an {@link AddressResolverGroup} which resolves remote addresses into * {@link InetSocketAddress}es. */ - public static final ClientFactoryOption>> ADDRESS_RESOLVER_GROUP_FACTORY = ClientFactoryOption - .define("ADDRESS_RESOLVER_GROUP_FACTORY", - eventLoopGroup -> new DnsResolverGroupBuilder().build(eventLoopGroup)); + public static final ClientFactoryOption>> ADDRESS_RESOLVER_GROUP_FACTORY = + ClientFactoryOption.define("ADDRESS_RESOLVER_GROUP_FACTORY", + eventLoopGroup -> new DnsResolverGroupBuilder().build(eventLoopGroup)); /** - * The HTTP/2 - * initial - * connection flow-control + * The HTTP/2 initial connection flow-control * window size. */ - public static final ClientFactoryOption HTTP2_INITIAL_CONNECTION_WINDOW_SIZE = ClientFactoryOption.define( - "HTTP2_INITIAL_CONNECTION_WINDOW_SIZE", - Flags.defaultHttp2InitialConnectionWindowSize()); + public static final ClientFactoryOption HTTP2_INITIAL_CONNECTION_WINDOW_SIZE = + ClientFactoryOption.define("HTTP2_INITIAL_CONNECTION_WINDOW_SIZE", + Flags.defaultHttp2InitialConnectionWindowSize()); /** - * The SETTINGS_INITIAL_WINDOW_SIZE + * The SETTINGS_INITIAL_WINDOW_SIZE * for HTTP/2 stream-level flow control. */ - public static final ClientFactoryOption HTTP2_INITIAL_STREAM_WINDOW_SIZE = ClientFactoryOption.define( - "HTTP2_INITIAL_STREAM_WINDOW_SIZE", - Flags.defaultHttp2InitialStreamWindowSize()); + public static final ClientFactoryOption HTTP2_INITIAL_STREAM_WINDOW_SIZE = + ClientFactoryOption.define("HTTP2_INITIAL_STREAM_WINDOW_SIZE", + Flags.defaultHttp2InitialStreamWindowSize()); /** - * The SETTINGS_MAX_FRAME_SIZE - * that indicates the size of the largest frame payload that this client is - * willing to receive. + * The SETTINGS_MAX_FRAME_SIZE + * that indicates the size of the largest frame payload that this client is willing to receive. */ - public static final ClientFactoryOption HTTP2_MAX_FRAME_SIZE = ClientFactoryOption - .define("HTTP2_MAX_FRAME_SIZE", Flags.defaultHttp2MaxFrameSize()); + public static final ClientFactoryOption HTTP2_MAX_FRAME_SIZE = + ClientFactoryOption.define("HTTP2_MAX_FRAME_SIZE", Flags.defaultHttp2MaxFrameSize()); /** - * The HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE - * that indicates the maximum size of header list that the client is prepared to - * accept, in octets. + * The HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE + * that indicates the maximum size of header list that the client is prepared to accept, in octets. */ - public static final ClientFactoryOption HTTP2_MAX_HEADER_LIST_SIZE = ClientFactoryOption - .define("HTTP2_MAX_HEADER_LIST_SIZE", Flags.defaultHttp2MaxHeaderListSize()); + public static final ClientFactoryOption HTTP2_MAX_HEADER_LIST_SIZE = + ClientFactoryOption.define("HTTP2_MAX_HEADER_LIST_SIZE", Flags.defaultHttp2MaxHeaderListSize()); /** * The maximum length of an HTTP/1 response initial line. */ - public static final ClientFactoryOption HTTP1_MAX_INITIAL_LINE_LENGTH = ClientFactoryOption.define( - "HTTP1_MAX_INITIAL_LINE_LENGTH", - Flags.defaultHttp1MaxInitialLineLength()); + public static final ClientFactoryOption HTTP1_MAX_INITIAL_LINE_LENGTH = + ClientFactoryOption.define("HTTP1_MAX_INITIAL_LINE_LENGTH", + Flags.defaultHttp1MaxInitialLineLength()); /** * The maximum length of all headers in an HTTP/1 response. */ - public static final ClientFactoryOption HTTP1_MAX_HEADER_SIZE = ClientFactoryOption - .define("HTTP1_MAX_HEADER_SIZE", Flags.defaultHttp1MaxHeaderSize()); + public static final ClientFactoryOption HTTP1_MAX_HEADER_SIZE = + ClientFactoryOption.define("HTTP1_MAX_HEADER_SIZE", Flags.defaultHttp1MaxHeaderSize()); /** * The maximum length of each chunk in an HTTP/1 response content. */ - public static final ClientFactoryOption HTTP1_MAX_CHUNK_SIZE = ClientFactoryOption - .define("HTTP1_MAX_CHUNK_SIZE", Flags.defaultHttp1MaxChunkSize()); + public static final ClientFactoryOption HTTP1_MAX_CHUNK_SIZE = + ClientFactoryOption.define("HTTP1_MAX_CHUNK_SIZE", Flags.defaultHttp1MaxChunkSize()); /** * The idle timeout of a socket connection in milliseconds. */ - public static final ClientFactoryOption IDLE_TIMEOUT_MILLIS = ClientFactoryOption.define("IDLE_TIMEOUT_MILLIS", - Flags.defaultClientIdleTimeoutMillis()); + public static final ClientFactoryOption IDLE_TIMEOUT_MILLIS = + ClientFactoryOption.define("IDLE_TIMEOUT_MILLIS", Flags.defaultClientIdleTimeoutMillis()); /** - * If the idle timeout is reset when an HTTP/2 PING frame or the response of - * {@code "OPTIONS * HTTP/1.1"} + * If the idle timeout is reset when an HTTP/2 PING frame or the response of {@code "OPTIONS * HTTP/1.1"} * is received. */ @UnstableApi - public static final ClientFactoryOption KEEP_ALIVE_ON_PING = ClientFactoryOption.define("KEEP_ALIVE_ON_PING", - Flags.defaultClientKeepAliveOnPing()); + public static final ClientFactoryOption KEEP_ALIVE_ON_PING = + ClientFactoryOption.define("KEEP_ALIVE_ON_PING", Flags.defaultClientKeepAliveOnPing()); /** * The PING interval in milliseconds. * When neither read nor write was performed for the specified period of time, - * a - * PING - * frame is sent for HTTP/2 - * or an OPTIONS - * request with + * a PING frame is sent for HTTP/2 + * or an OPTIONS request with * an asterisk ("*") is sent for HTTP/1. */ - public static final ClientFactoryOption PING_INTERVAL_MILLIS = ClientFactoryOption - .define("PING_INTERVAL_MILLIS", Flags.defaultPingIntervalMillis()); + public static final ClientFactoryOption PING_INTERVAL_MILLIS = + ClientFactoryOption.define("PING_INTERVAL_MILLIS", Flags.defaultPingIntervalMillis()); /** * The client-side max age of a connection for keep-alive in milliseconds. - * If the value is greater than {@code 0}, a connection is disconnected after - * the specified + * If the value is greater than {@code 0}, a connection is disconnected after the specified * amount of time since the connection was established. * This option is disabled by default, which means unlimited. */ - public static final ClientFactoryOption MAX_CONNECTION_AGE_MILLIS = ClientFactoryOption - .define("MAX_CONNECTION_AGE_MILLIS", clampedDefaultMaxClientConnectionAge()); + public static final ClientFactoryOption MAX_CONNECTION_AGE_MILLIS = + ClientFactoryOption.define("MAX_CONNECTION_AGE_MILLIS", clampedDefaultMaxClientConnectionAge()); private static long clampedDefaultMaxClientConnectionAge() { final long connectionAgeMillis = Flags.defaultMaxClientConnectionAgeMillis(); @@ -244,122 +221,111 @@ private static long clampedDefaultMaxClientConnectionAge() { } /** - * The client-side maximum allowed number of requests that can be sent through - * one connection. + * The client-side maximum allowed number of requests that can be sent through one connection. * This option is disabled by default, which means unlimited. */ - public static final ClientFactoryOption MAX_NUM_REQUESTS_PER_CONNECTION = ClientFactoryOption.define( - "MAX_NUM_REQUESTS_PER_CONNECTION", - Flags.defaultMaxClientNumRequestsPerConnection()); + public static final ClientFactoryOption MAX_NUM_REQUESTS_PER_CONNECTION = + ClientFactoryOption.define("MAX_NUM_REQUESTS_PER_CONNECTION", + Flags.defaultMaxClientNumRequestsPerConnection()); /** - * Whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request - * to negotiate + * Whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request to negotiate * the protocol version of a cleartext HTTP connection. */ - public static final ClientFactoryOption USE_HTTP2_PREFACE = ClientFactoryOption.define("USE_HTTP2_PREFACE", - Flags.defaultUseHttp2Preface()); + public static final ClientFactoryOption USE_HTTP2_PREFACE = + ClientFactoryOption.define("USE_HTTP2_PREFACE", Flags.defaultUseHttp2Preface()); /** - * Whether to use HTTP/1.1 instead of HTTP/2. If enabled, the client will not - * attempt to upgrade to + * Whether to use HTTP/1.1 instead of HTTP/2. If enabled, the client will not attempt to upgrade to * HTTP/2 for {@link SessionProtocol#HTTP} and {@link SessionProtocol#HTTPS}. */ @UnstableApi - public static final ClientFactoryOption PREFER_HTTP1 = ClientFactoryOption.define("PREFER_HTTP1", - Flags.defaultPreferHttp1()); + public static final ClientFactoryOption PREFER_HTTP1 = + ClientFactoryOption.define("PREFER_HTTP1", Flags.defaultPreferHttp1()); /** - * Whether to use HTTP/2 without ALPN. This is useful if you want to communicate - * with an HTTP/2 + * Whether to use HTTP/2 without ALPN. This is useful if you want to communicate with an HTTP/2 * server over TLS but the server does not support ALPN. */ @UnstableApi - public static final ClientFactoryOption USE_HTTP2_WITHOUT_ALPN = ClientFactoryOption - .define("USE_HTTP2_WITHOUT_ALPN", Flags.defaultUseHttp2WithoutAlpn()); + public static final ClientFactoryOption USE_HTTP2_WITHOUT_ALPN = + ClientFactoryOption.define("USE_HTTP2_WITHOUT_ALPN", Flags.defaultUseHttp2WithoutAlpn()); /** - * Whether to use HTTP - * pipelining for + * Whether to use HTTP pipelining for * HTTP/1 connections. */ - public static final ClientFactoryOption USE_HTTP1_PIPELINING = ClientFactoryOption - .define("USE_HTTP1_PIPELINING", Flags.defaultUseHttp1Pipelining()); + public static final ClientFactoryOption USE_HTTP1_PIPELINING = + ClientFactoryOption.define("USE_HTTP1_PIPELINING", Flags.defaultUseHttp1Pipelining()); /** * The listener which is notified on a connection pool event. */ - public static final ClientFactoryOption CONNECTION_POOL_LISTENER = ClientFactoryOption - .define("CONNECTION_POOL_LISTENER", ConnectionPoolListener.noop()); + public static final ClientFactoryOption CONNECTION_POOL_LISTENER = + ClientFactoryOption.define("CONNECTION_POOL_LISTENER", ConnectionPoolListener.noop()); /** * The {@link MeterRegistry} which collects various stats. */ - public static final ClientFactoryOption METER_REGISTRY = ClientFactoryOption.define("METER_REGISTRY", - Flags.meterRegistry()); + public static final ClientFactoryOption METER_REGISTRY = + ClientFactoryOption.define("METER_REGISTRY", Flags.meterRegistry()); /** - * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to - * be used. + * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to be used. */ - public static final ClientFactoryOption PROXY_CONFIG_SELECTOR = ClientFactoryOption - .define("PROXY_CONFIG_SELECTOR", ProxyConfigSelector.of(ProxyConfig.direct())); + public static final ClientFactoryOption PROXY_CONFIG_SELECTOR = + ClientFactoryOption.define("PROXY_CONFIG_SELECTOR", ProxyConfigSelector.of(ProxyConfig.direct())); /** - * The {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name - * into + * The {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name into * another HTTP/1 header name. */ - public static final ClientFactoryOption HTTP1_HEADER_NAMING = ClientFactoryOption - .define("HTTP1_HEADER_NAMING", Http1HeaderNaming.ofDefault()); - - /** - * The {@link ChannelOption}s of the sockets created by the - * {@link ClientFactory}. - */ - public static final ClientFactoryOption, Object>> CHANNEL_OPTIONS = ClientFactoryOption - .define("CHANNEL_OPTIONS", ImmutableMap.of(), newOptions -> { - for (ChannelOption channelOption : ChannelUtil.prohibitedOptions()) { - checkArgument(!newOptions.containsKey(channelOption), - "prohibited channel option: %s", channelOption); - } - return newOptions; - }, (oldValue, newValue) -> { - final Map, Object> newOptions = newValue.value(); - if (newOptions.isEmpty()) { - return oldValue; - } - final Map, Object> oldOptions = oldValue.value(); - if (oldOptions.isEmpty()) { - return newValue; - } - final ImmutableMap.Builder, Object> builder = ImmutableMap - .builderWithExpectedSize(oldOptions.size() + newOptions.size()); - oldOptions.forEach((key, value) -> { - if (!newOptions.containsKey(key)) { - builder.put(key, value); - } - }); - builder.putAll(newOptions); - return newValue.option().newValue(builder.build()); - }); + public static final ClientFactoryOption HTTP1_HEADER_NAMING = + ClientFactoryOption.define("HTTP1_HEADER_NAMING", Http1HeaderNaming.ofDefault()); + + /** + * The {@link ChannelOption}s of the sockets created by the {@link ClientFactory}. + */ + public static final ClientFactoryOption, Object>> CHANNEL_OPTIONS = + ClientFactoryOption.define("CHANNEL_OPTIONS", ImmutableMap.of(), newOptions -> { + for (ChannelOption channelOption : ChannelUtil.prohibitedOptions()) { + checkArgument(!newOptions.containsKey(channelOption), + "prohibited channel option: %s", channelOption); + } + return newOptions; + }, (oldValue, newValue) -> { + final Map, Object> newOptions = newValue.value(); + if (newOptions.isEmpty()) { + return oldValue; + } + final Map, Object> oldOptions = oldValue.value(); + if (oldOptions.isEmpty()) { + return newValue; + } + final ImmutableMap.Builder, Object> builder = + ImmutableMap.builderWithExpectedSize(oldOptions.size() + newOptions.size()); + oldOptions.forEach((key, value) -> { + if (!newOptions.containsKey(key)) { + builder.put(key, value); + } + }); + builder.putAll(newOptions); + return newValue.option().newValue(builder.build()); + }); /** * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. - * This customizer is run right before - * {@link ChannelPipeline#connect(SocketAddress)} + * This customizer is run right before {@link ChannelPipeline#connect(SocketAddress)} * is invoked by Armeria. This customizer is no-op by default. * - *

- * Note that usage of this customizer is an advanced + *

Note that usage of this customizer is an advanced * feature and may produce unintended side effects, including complete * breakdown. It is not recommended if you are not familiar with * Armeria and Netty internals. */ @UnstableApi - public static final ClientFactoryOption> CHANNEL_PIPELINE_CUSTOMIZER = ClientFactoryOption - .define("CHANNEL_PIPELINE_CUSTOMIZER", v -> { - /* no-op */ }); + public static final ClientFactoryOption> CHANNEL_PIPELINE_CUSTOMIZER = + ClientFactoryOption.define("CHANNEL_PIPELINE_CUSTOMIZER", v -> { /* no-op */ }); private static final ClientFactoryOptions EMPTY = new ClientFactoryOptions(ImmutableList.of()); @@ -371,8 +337,7 @@ public static ClientFactoryOptions of() { } /** - * Returns the {@link ClientFactoryOptions} with the specified - * {@link ClientFactoryOptionValue}s. + * Returns the {@link ClientFactoryOptions} with the specified {@link ClientFactoryOptionValue}s. */ public static ClientFactoryOptions of(ClientFactoryOptionValue... values) { requireNonNull(values, "values"); @@ -383,8 +348,7 @@ public static ClientFactoryOptions of(ClientFactoryOptionValue... values) { } /** - * Returns the {@link ClientFactoryOptions} with the specified - * {@link ClientFactoryOptionValue}s. + * Returns the {@link ClientFactoryOptions} with the specified {@link ClientFactoryOptionValue}s. */ public static ClientFactoryOptions of(Iterable> values) { requireNonNull(values, "values"); @@ -395,13 +359,12 @@ public static ClientFactoryOptions of(Iterable... additionalValues) { + ClientFactoryOptionValue... additionalValues) { requireNonNull(baseOptions, "baseOptions"); requireNonNull(additionalValues, "additionalValues"); if (additionalValues.length == 0) { @@ -411,13 +374,12 @@ public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, } /** - * Merges the specified {@link ClientFactoryOptions} and - * {@link ClientFactoryOptionValue}s. + * Merges the specified {@link ClientFactoryOptions} and {@link ClientFactoryOptionValue}s. * * @return the merged {@link ClientFactoryOptions} */ public static ClientFactoryOptions of(ClientFactoryOptions baseOptions, - Iterable> additionalValues) { + Iterable> additionalValues) { requireNonNull(baseOptions, "baseOptions"); requireNonNull(additionalValues, "additionalValues"); return new ClientFactoryOptions(baseOptions, additionalValues); @@ -428,7 +390,7 @@ private ClientFactoryOptions(Iterable> val } private ClientFactoryOptions(ClientFactoryOptions baseOptions, - Iterable> additionalValues) { + Iterable> additionalValues) { super(baseOptions, additionalValues); } @@ -449,8 +411,7 @@ public boolean shutdownWorkerGroupOnClose() { } /** - * Returns the factory that creates an {@link EventLoopScheduler} which is - * responsible for assigning an + * Returns the factory that creates an {@link EventLoopScheduler} which is responsible for assigning an * {@link EventLoop} to handle a connection to the specified {@link Endpoint}. */ public Function eventLoopSchedulerFactory() { @@ -458,16 +419,14 @@ public boolean shutdownWorkerGroupOnClose() { } /** - * Returns the {@link ChannelOption}s of the sockets created by the - * {@link ClientFactory}. + * Returns the {@link ChannelOption}s of the sockets created by the {@link ClientFactory}. */ public Map, Object> channelOptions() { return get(CHANNEL_OPTIONS); } /** - * Returns the {@link Consumer} which can arbitrarily configure the - * {@link SslContextBuilder} that will be + * Returns the {@link Consumer} which can arbitrarily configure the {@link SslContextBuilder} that will be * applied to the SSL session. */ public Consumer tlsCustomizer() { @@ -475,19 +434,17 @@ public Consumer tlsCustomizer() { } /** - * Returns the factory that creates an {@link AddressResolverGroup} which - * resolves remote addresses into + * Returns the factory that creates an {@link AddressResolverGroup} which resolves remote addresses into * {@link InetSocketAddress}es. */ - public Function> addressResolverGroupFactory() { + public Function> addressResolverGroupFactory() { return get(ADDRESS_RESOLVER_GROUP_FACTORY); } /** - * Returns the HTTP/2 - * initial - * connection + * Returns the HTTP/2 initial connection * flow-control window size. */ public int http2InitialConnectionWindowSize() { @@ -495,8 +452,7 @@ public int http2InitialConnectionWindowSize() { } /** - * Returns the SETTINGS_INITIAL_WINDOW_SIZE + * Returns the SETTINGS_INITIAL_WINDOW_SIZE * for HTTP/2 stream-level flow control. */ public int http2InitialStreamWindowSize() { @@ -504,20 +460,16 @@ public int http2InitialStreamWindowSize() { } /** - * Returns the SETTINGS_MAX_FRAME_SIZE - * that indicates the size of the largest frame payload that this client is - * willing to receive. + * Returns the SETTINGS_MAX_FRAME_SIZE + * that indicates the size of the largest frame payload that this client is willing to receive. */ public int http2MaxFrameSize() { return get(HTTP2_MAX_FRAME_SIZE); } /** - * Returns the HTTP/2 - * - * SETTINGS_MAX_HEADER_LIST_SIZE that indicates the maximum size of header - * list + * Returns the HTTP/2 + * SETTINGS_MAX_HEADER_LIST_SIZE that indicates the maximum size of header list * that the client is prepared to accept, in octets. */ public long http2MaxHeaderListSize() { @@ -553,8 +505,7 @@ public long idleTimeoutMillis() { } /** - * Returns whether to keep connection alive when an HTTP/2 PING frame or the - * response of + * Returns whether to keep connection alive when an HTTP/2 PING frame or the response of * {@code "OPTIONS * HTTP/1.1"} is received. */ @UnstableApi @@ -565,12 +516,8 @@ public boolean keepAliveOnPing() { /** * Returns the PING interval in milliseconds. * When neither read nor write was performed for the specified period of time, - * a - * PING - * frame is sent for HTTP/2 - * or an OPTIONS - * request with + * a PING frame is sent for HTTP/2 + * or an OPTIONS request with * an asterisk ("*") is sent for HTTP/1. */ public long pingIntervalMillis() { @@ -578,10 +525,8 @@ public long pingIntervalMillis() { } /** - * Returns the client-side max age of a connection for keep-alive in - * milliseconds. - * If the value is greater than {@code 0}, a connection is disconnected after - * the specified + * Returns the client-side max age of a connection for keep-alive in milliseconds. + * If the value is greater than {@code 0}, a connection is disconnected after the specified * amount of the time since the connection was established. */ public long maxConnectionAgeMillis() { @@ -589,16 +534,14 @@ public long maxConnectionAgeMillis() { } /** - * Returns the client-side maximum allowed number of requests that can be sent - * through one connection. + * Returns the client-side maximum allowed number of requests that can be sent through one connection. */ public int maxNumRequestsPerConnection() { return get(MAX_NUM_REQUESTS_PER_CONNECTION); } /** - * Returns whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade - * request to negotiate + * Returns whether to send an HTTP/2 preface string instead of an HTTP/1 upgrade request to negotiate * the protocol version of a cleartext HTTP connection. */ public boolean useHttp2Preface() { @@ -606,10 +549,8 @@ public boolean useHttp2Preface() { } /** - * Returns whether to use HTTP/1.1 instead of HTTP/2 . If {@code true}, the - * client will not attempt to - * upgrade to HTTP/2 for {@link SessionProtocol#HTTP} and - * {@link SessionProtocol#HTTPS}. + * Returns whether to use HTTP/1.1 instead of HTTP/2 . If {@code true}, the client will not attempt to + * upgrade to HTTP/2 for {@link SessionProtocol#HTTP} and {@link SessionProtocol#HTTPS}. */ @UnstableApi public boolean preferHttp1() { @@ -625,9 +566,7 @@ public boolean useHttp2WithoutAlpn() { } /** - * Returns whether to use - * HTTP pipelining - * for + * Returns whether to use HTTP pipelining for * HTTP/1 connections. */ public boolean useHttp1Pipelining() { @@ -649,18 +588,15 @@ public MeterRegistry meterRegistry() { } /** - * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to - * be used. + * The {@link ProxyConfigSelector} which determines the {@link ProxyConfig} to be used. */ public ProxyConfigSelector proxyConfigSelector() { return get(PROXY_CONFIG_SELECTOR); } /** - * Returns the {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 - * header name into - * another header name. This is useful when communicating with a legacy system - * that only supports + * Returns the {@link Http1HeaderNaming} which converts a lower-cased HTTP/2 header name into + * another header name. This is useful when communicating with a legacy system that only supports * case-sensitive HTTP/1 headers. */ public Http1HeaderNaming http1HeaderNaming() { @@ -669,19 +605,12 @@ public Http1HeaderNaming http1HeaderNaming() { /** * Returns whether to allow the bad cipher suites listed in - * RFC7540 for - * TLS handshake. + * RFC7540 for TLS handshake. * - *

- * Note that enabling this option increases the security risk of your - * connection. - * Use it only when you must communicate with a legacy system that does not - * support + *

Note that enabling this option increases the security risk of your connection. + * Use it only when you must communicate with a legacy system that does not support * secure cipher suites. - * See - * Section - * 9.2.2, RFC7540 for + * See Section 9.2.2, RFC7540 for * more information. */ public boolean tlsAllowUnsafeCiphers() { @@ -690,12 +619,10 @@ public boolean tlsAllowUnsafeCiphers() { /** * The {@link Consumer} that customizes the Netty {@link ChannelPipeline}. - * This customizer is run right before - * {@link ChannelPipeline#connect(SocketAddress)} + * This customizer is run right before {@link ChannelPipeline#connect(SocketAddress)} * is invoked by Armeria. This customizer is no-op by default. * - *

- * Note that usage of this customizer is an advanced + *

Note that usage of this customizer is an advanced * feature and may produce unintended side effects, including complete * breakdown. It is not recommended if you are not familiar with * Armeria and Netty internals.