1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.http;
17 
18 import java.time.Duration;
19 import software.amazon.awssdk.annotations.SdkProtectedApi;
20 import software.amazon.awssdk.utils.AttributeMap;
21 
22 /**
23  * Type safe key for an HTTP related configuration option. These options are used for service specific configuration
24  * and are treated as hints for the underlying HTTP implementation for better defaults. If an implementation does not support
25  * a particular option, they are free to ignore it.
26  *
27  * @param <T> Type of option
28  * @see AttributeMap
29  */
30 @SdkProtectedApi
31 public final class SdkHttpConfigurationOption<T> extends AttributeMap.Key<T> {
32     /**
33      * Timeout for each read to the underlying socket.
34      */
35     public static final SdkHttpConfigurationOption<Duration> READ_TIMEOUT =
36             new SdkHttpConfigurationOption<>("ReadTimeout", Duration.class);
37 
38     /**
39      * Timeout for each write to the underlying socket.
40      */
41     public static final SdkHttpConfigurationOption<Duration> WRITE_TIMEOUT =
42             new SdkHttpConfigurationOption<>("WriteTimeout", Duration.class);
43 
44     /**
45      * Timeout for establishing a connection to a remote service.
46      */
47     public static final SdkHttpConfigurationOption<Duration> CONNECTION_TIMEOUT =
48             new SdkHttpConfigurationOption<>("ConnectionTimeout", Duration.class);
49 
50     /**
51      * Timeout for acquiring an already-established connection from a connection pool to a remote service.
52      */
53     public static final SdkHttpConfigurationOption<Duration> CONNECTION_ACQUIRE_TIMEOUT =
54             new SdkHttpConfigurationOption<>("ConnectionAcquireTimeout", Duration.class);
55 
56     /**
57      * Timeout after which an idle connection should be closed.
58      */
59     public static final SdkHttpConfigurationOption<Duration> CONNECTION_MAX_IDLE_TIMEOUT =
60             new SdkHttpConfigurationOption<>("ConnectionMaxIdleTimeout", Duration.class);
61 
62     /**
63      * Timeout after which a connection should be closed, regardless of whether it is idle. Zero indicates an infinite amount
64      * of time.
65      */
66     public static final SdkHttpConfigurationOption<Duration> CONNECTION_TIME_TO_LIVE =
67             new SdkHttpConfigurationOption<>("ConnectionTimeToLive", Duration.class);
68 
69     /**
70      * Maximum number of connections allowed in a connection pool.
71      */
72     public static final SdkHttpConfigurationOption<Integer> MAX_CONNECTIONS =
73             new SdkHttpConfigurationOption<>("MaxConnections", Integer.class);
74 
75     /**
76      * HTTP protocol to use.
77      */
78     public static final SdkHttpConfigurationOption<Protocol> PROTOCOL =
79         new SdkHttpConfigurationOption<>("Protocol", Protocol.class);
80 
81     /**
82      * Maximum number of requests allowed to wait for a connection.
83      */
84     public static final SdkHttpConfigurationOption<Integer> MAX_PENDING_CONNECTION_ACQUIRES =
85             new SdkHttpConfigurationOption<>("MaxConnectionAcquires", Integer.class);
86 
87     /**
88      * Whether idle connection should be removed after the {@link #CONNECTION_MAX_IDLE_TIMEOUT} has passed.
89      */
90     public static final SdkHttpConfigurationOption<Boolean> REAP_IDLE_CONNECTIONS =
91             new SdkHttpConfigurationOption<>("ReapIdleConnections", Boolean.class);
92 
93     /**
94      * Whether to enable or disable TCP KeepAlive.
95      * <p>
96      * When enabled, the actual KeepAlive mechanism is dependent on the Operating System and therefore additional TCP KeepAlive
97      * values (like timeout, number of packets, etc) must be configured via the Operating System (sysctl on Linux/Mac, and
98      * Registry values on Windows).
99      */
100     public static final SdkHttpConfigurationOption<Boolean> TCP_KEEPALIVE =
101         new SdkHttpConfigurationOption<>("TcpKeepalive", Boolean.class);
102 
103     /**
104      * The {@link TlsKeyManagersProvider} that will be used by the HTTP client when authenticating with a
105      * TLS host.
106      */
107     public static final SdkHttpConfigurationOption<TlsKeyManagersProvider> TLS_KEY_MANAGERS_PROVIDER =
108             new SdkHttpConfigurationOption<>("TlsKeyManagersProvider", TlsKeyManagersProvider.class);
109 
110     /**
111      * Option to disable SSL cert validation and SSL host name verification. By default, this option is off.
112      * Only enable this option for testing purposes.
113      */
114     public static final SdkHttpConfigurationOption<Boolean> TRUST_ALL_CERTIFICATES =
115         new SdkHttpConfigurationOption<>("TrustAllCertificates", Boolean.class);
116 
117     /**
118      * The {@link TlsTrustManagersProvider} that will be used by the HTTP client when authenticating with a
119      * TLS host.
120      */
121     public static final SdkHttpConfigurationOption<TlsTrustManagersProvider> TLS_TRUST_MANAGERS_PROVIDER =
122         new SdkHttpConfigurationOption<>("TlsTrustManagersProvider", TlsTrustManagersProvider.class);
123 
124     /**
125      * The maximum amount of time that a TLS handshake is allowed to take from the time the CLIENT HELLO
126      * message is sent to the time the client and server have fully negotiated ciphers and exchanged keys.
127      *
128      * <p>
129      * If not specified, the default value will be the same as the resolved {@link #CONNECTION_TIMEOUT}.
130      */
131     public static final SdkHttpConfigurationOption<Duration> TLS_NEGOTIATION_TIMEOUT =
132         new SdkHttpConfigurationOption<>("TlsNegotiationTimeout", Duration.class);
133 
134     private static final Duration DEFAULT_SOCKET_READ_TIMEOUT = Duration.ofSeconds(30);
135     private static final Duration DEFAULT_SOCKET_WRITE_TIMEOUT = Duration.ofSeconds(30);
136     private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(2);
137     private static final Duration DEFAULT_CONNECTION_ACQUIRE_TIMEOUT = Duration.ofSeconds(10);
138     private static final Duration DEFAULT_CONNECTION_MAX_IDLE_TIMEOUT = Duration.ofSeconds(60);
139     private static final Duration DEFAULT_CONNECTION_TIME_TO_LIVE = Duration.ZERO;
140     /**
141      * 5 seconds = 3 seconds (RTO for 2 packets loss) + 2 seconds (startup latency and RTT buffer)
142      */
143     private static final Duration DEFAULT_TLS_NEGOTIATION_TIMEOUT = Duration.ofSeconds(5);
144     private static final Boolean DEFAULT_REAP_IDLE_CONNECTIONS = Boolean.TRUE;
145     private static final int DEFAULT_MAX_CONNECTIONS = 50;
146     private static final int DEFAULT_MAX_CONNECTION_ACQUIRES = 10_000;
147     private static final Boolean DEFAULT_TCP_KEEPALIVE = Boolean.FALSE;
148     private static final Boolean DEFAULT_TRUST_ALL_CERTIFICATES = Boolean.FALSE;
149 
150     private static final Protocol DEFAULT_PROTOCOL = Protocol.HTTP1_1;
151 
152     private static final TlsTrustManagersProvider DEFAULT_TLS_TRUST_MANAGERS_PROVIDER = null;
153     private static final TlsKeyManagersProvider DEFAULT_TLS_KEY_MANAGERS_PROVIDER = SystemPropertyTlsKeyManagersProvider.create();
154 
155     public static final AttributeMap GLOBAL_HTTP_DEFAULTS = AttributeMap
156             .builder()
157             .put(READ_TIMEOUT, DEFAULT_SOCKET_READ_TIMEOUT)
158             .put(WRITE_TIMEOUT, DEFAULT_SOCKET_WRITE_TIMEOUT)
159             .put(CONNECTION_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT)
160             .put(CONNECTION_ACQUIRE_TIMEOUT, DEFAULT_CONNECTION_ACQUIRE_TIMEOUT)
161             .put(CONNECTION_MAX_IDLE_TIMEOUT, DEFAULT_CONNECTION_MAX_IDLE_TIMEOUT)
162             .put(CONNECTION_TIME_TO_LIVE, DEFAULT_CONNECTION_TIME_TO_LIVE)
163             .put(MAX_CONNECTIONS, DEFAULT_MAX_CONNECTIONS)
164             .put(MAX_PENDING_CONNECTION_ACQUIRES, DEFAULT_MAX_CONNECTION_ACQUIRES)
165             .put(PROTOCOL, DEFAULT_PROTOCOL)
166             .put(TRUST_ALL_CERTIFICATES, DEFAULT_TRUST_ALL_CERTIFICATES)
167             .put(REAP_IDLE_CONNECTIONS, DEFAULT_REAP_IDLE_CONNECTIONS)
168             .put(TCP_KEEPALIVE, DEFAULT_TCP_KEEPALIVE)
169             .put(TLS_KEY_MANAGERS_PROVIDER, DEFAULT_TLS_KEY_MANAGERS_PROVIDER)
170             .put(TLS_TRUST_MANAGERS_PROVIDER, DEFAULT_TLS_TRUST_MANAGERS_PROVIDER)
171             .put(TLS_NEGOTIATION_TIMEOUT, DEFAULT_TLS_NEGOTIATION_TIMEOUT)
172             .build();
173 
174     private final String name;
175 
SdkHttpConfigurationOption(String name, Class<T> clzz)176     private SdkHttpConfigurationOption(String name, Class<T> clzz) {
177         super(clzz);
178         this.name = name;
179     }
180 
181     /**
182      * Note that the name is mainly used for debugging purposes. Two option key objects with the same name do not represent
183      * the same option. Option keys are compared by reference when obtaining a value from an {@link AttributeMap}.
184      *
185      * @return Name of this option key.
186      */
name()187     public String name() {
188         return name;
189     }
190 
191     @Override
toString()192     public String toString() {
193         return name;
194     }
195 }
196 
197