/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.http.crt; import static software.amazon.awssdk.crtcore.CrtConfigurationUtils.resolveHttpMonitoringOptions; import static software.amazon.awssdk.crtcore.CrtConfigurationUtils.resolveProxy; import static software.amazon.awssdk.http.HttpMetric.HTTP_CLIENT_NAME; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL; import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.buildSocketOptions; import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.resolveCipherPreference; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import static software.amazon.awssdk.utils.Validate.paramNotNull; import java.net.URI; import java.time.Duration; import java.util.LinkedList; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.crt.CrtResource; import software.amazon.awssdk.crt.http.HttpClientConnectionManager; import software.amazon.awssdk.crt.http.HttpClientConnectionManagerOptions; import software.amazon.awssdk.crt.http.HttpMonitoringOptions; import software.amazon.awssdk.crt.http.HttpProxyOptions; import software.amazon.awssdk.crt.io.ClientBootstrap; import software.amazon.awssdk.crt.io.SocketOptions; import software.amazon.awssdk.crt.io.TlsContext; import software.amazon.awssdk.crt.io.TlsContextOptions; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.SdkHttpConfigurationOption; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.async.AsyncExecuteRequest; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.crt.internal.CrtRequestContext; import software.amazon.awssdk.http.crt.internal.CrtRequestExecutor; import software.amazon.awssdk.metrics.NoOpMetricCollector; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Validate; /** * An implementation of {@link SdkAsyncHttpClient} that uses the AWS Common Runtime (CRT) Http Client to communicate with * Http Web Services. This client is asynchronous and uses non-blocking IO. * *
This can be created via {@link #builder()}
* {@snippet : SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder() .maxConcurrency(100) .connectionTimeout(Duration.ofSeconds(1)) .connectionMaxIdleTime(Duration.ofSeconds(5)) .build(); * } * */ @SdkPublicApi public final class AwsCrtAsyncHttpClient implements SdkAsyncHttpClient { private static final Logger log = Logger.loggerFor(AwsCrtAsyncHttpClient.class); private static final String AWS_COMMON_RUNTIME = "AwsCommonRuntime"; private static final long DEFAULT_STREAM_WINDOW_SIZE = 16L * 1024L * 1024L; // 16 MB private final Map* You can set a throughput threshold for a connection to be considered healthy. * If a connection falls below this threshold ({@link ConnectionHealthConfiguration#minimumThroughputInBps() * }) for the configurable amount * of time ({@link ConnectionHealthConfiguration#minimumThroughputTimeout()}), * then the connection is considered unhealthy and will be shut down. * *
* By default, monitoring options are disabled. You can enable {@code healthChecks} by providing this configuration
* and specifying the options for monitoring for the connection manager.
* @param healthChecksConfiguration The health checks config to use
* @return The builder of the method chaining.
*/
Builder connectionHealthConfiguration(ConnectionHealthConfiguration healthChecksConfiguration);
/**
* A convenience method that creates an instance of the {@link ConnectionHealthConfiguration} builder, avoiding the
* need to create one manually via {@link ConnectionHealthConfiguration#builder()}.
*
* @param healthChecksConfigurationBuilder The health checks config builder to use
* @return The builder of the method chaining.
* @see #connectionHealthConfiguration(ConnectionHealthConfiguration)
*/
Builder connectionHealthConfiguration(Consumer
* By default, tcpKeepAlive is disabled. You can enable {@code tcpKeepAlive} by providing this configuration
* and specifying periodic TCP keepalive packet intervals and timeouts. This may be required for certain connections for
* longer durations than default socket timeouts.
*
* @param tcpKeepAliveConfiguration The TCP keep-alive configuration to use
* @return The builder of the method chaining.
*/
Builder tcpKeepAliveConfiguration(TcpKeepAliveConfiguration tcpKeepAliveConfiguration);
/**
* Configure whether to enable {@code tcpKeepAlive} and relevant configuration for all connections established by this
* client.
*
*
* A convenience method that creates an instance of the {@link TcpKeepAliveConfiguration} builder, avoiding the
* need to create one manually via {@link TcpKeepAliveConfiguration#builder()}.
*
* @param tcpKeepAliveConfigurationBuilder The TCP keep-alive configuration builder to use
* @return The builder of the method chaining.
* @see #tcpKeepAliveConfiguration(TcpKeepAliveConfiguration)
*/
Builder tcpKeepAliveConfiguration(Consumer
* See Using hybrid post-quantum TLS with AWS KMS
*
*
* It's disabled by default.
*
* @param postQuantumTlsEnabled whether to prefer Post Quantum TLS
* @return The builder of the method chaining.
*/
Builder postQuantumTlsEnabled(Boolean postQuantumTlsEnabled);
}
/**
* Factory that allows more advanced configuration of the AWS CRT HTTP implementation. Use {@link #builder()} to
* configure and construct an immutable instance of the factory.
*/
private static final class DefaultBuilder implements Builder {
private final AttributeMap.Builder standardOptions = AttributeMap.builder();
private Long readBufferSize;
private ProxyConfiguration proxyConfiguration;
private ConnectionHealthConfiguration connectionHealthConfiguration;
private TcpKeepAliveConfiguration tcpKeepAliveConfiguration;
private Boolean postQuantumTlsEnabled;
private DefaultBuilder() {
}
@Override
public SdkAsyncHttpClient build() {
return new AwsCrtAsyncHttpClient(this, standardOptions.build()
.merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS));
}
@Override
public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
return new AwsCrtAsyncHttpClient(this, standardOptions.build()
.merge(serviceDefaults)
.merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS));
}
@Override
public Builder maxConcurrency(Integer maxConcurrency) {
Validate.isPositiveOrNull(maxConcurrency, "maxConcurrency");
standardOptions.put(SdkHttpConfigurationOption.MAX_CONNECTIONS, maxConcurrency);
return this;
}
@Override
public Builder readBufferSizeInBytes(Long readBufferSize) {
Validate.isPositiveOrNull(readBufferSize, "readBufferSize");
this.readBufferSize = readBufferSize;
return this;
}
@Override
public Builder proxyConfiguration(ProxyConfiguration proxyConfiguration) {
this.proxyConfiguration = proxyConfiguration;
return this;
}
@Override
public Builder connectionHealthConfiguration(ConnectionHealthConfiguration monitoringOptions) {
this.connectionHealthConfiguration = monitoringOptions;
return this;
}
@Override
public Builder connectionHealthConfiguration(Consumer