1
1
/*
2
- * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License").
5
5
* You may not use this file except in compliance with the License.
30
30
import software .amazon .awssdk .annotations .SdkPublicApi ;
31
31
import software .amazon .awssdk .crt .CrtResource ;
32
32
import software .amazon .awssdk .crt .http .HttpClientConnectionManager ;
33
+ import software .amazon .awssdk .crt .http .HttpClientConnectionManagerOptions ;
33
34
import software .amazon .awssdk .crt .http .HttpHeader ;
34
35
import software .amazon .awssdk .crt .http .HttpRequest ;
35
36
import software .amazon .awssdk .crt .io .ClientBootstrap ;
37
+ import software .amazon .awssdk .crt .io .EventLoopGroup ;
38
+ import software .amazon .awssdk .crt .io .HostResolver ;
36
39
import software .amazon .awssdk .crt .io .SocketOptions ;
37
40
import software .amazon .awssdk .crt .io .TlsCipherPreference ;
38
41
import software .amazon .awssdk .crt .io .TlsContext ;
@@ -80,9 +83,10 @@ public AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
80
83
int maxConns = config .get (SdkHttpConfigurationOption .MAX_CONNECTIONS );
81
84
82
85
Validate .isPositive (maxConns , "maxConns" );
83
- Validate .isPositive (builder .eventLoopSize , "eventLoopSize" );
84
86
Validate .notNull (builder .cipherPreference , "cipherPreference" );
85
87
Validate .isPositive (builder .windowSize , "windowSize" );
88
+ Validate .notNull (builder .eventLoopGroup , "eventLoopGroup" );
89
+ Validate .notNull (builder .hostResolver , "hostResolver" );
86
90
87
91
/**
88
92
* Must call own() in same order that CrtResources are created in, so that they will be closed in reverse order.
@@ -93,12 +97,16 @@ public AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
93
97
* in the correct order.
94
98
*/
95
99
96
- bootstrap = own (new ClientBootstrap (builder .eventLoopSize ));
97
- socketOptions = own (new SocketOptions ());
98
- tlsContextOptions = own (TlsContextOptions .createDefaultClient ().withCipherPreference (builder .cipherPreference ));
99
- tlsContextOptions .setVerifyPeer (builder .verifyPeer );
100
- tlsContext = own (new TlsContext (tlsContextOptions ));
100
+ this .bootstrap = own (new ClientBootstrap (builder .eventLoopGroup , builder .hostResolver ));
101
+ this .socketOptions = own (new SocketOptions ());
101
102
103
+ try (TlsContextOptions defaultClientOptions = TlsContextOptions .createDefaultClient ()
104
+ .withCipherPreference (builder .cipherPreference )
105
+ .withVerifyPeer (builder .verifyPeer )) {
106
+ this .tlsContextOptions = own (defaultClientOptions );
107
+ }
108
+
109
+ this .tlsContext = own (new TlsContext (this .tlsContextOptions ));
102
110
this .windowSize = builder .windowSize ;
103
111
this .maxConnectionsPerEndpoint = maxConns ;
104
112
}
@@ -135,8 +143,15 @@ private HttpClientConnectionManager createConnectionPool(URI uri) {
135
143
Validate .notNull (uri , "URI must not be null" );
136
144
log .debug (() -> "Creating ConnectionPool for: URI:" + uri + ", MaxConns: " + maxConnectionsPerEndpoint );
137
145
138
- return new HttpClientConnectionManager (bootstrap , socketOptions , tlsContext , uri , windowSize ,
139
- maxConnectionsPerEndpoint );
146
+ HttpClientConnectionManagerOptions options = new HttpClientConnectionManagerOptions ();
147
+ options .withClientBootstrap (bootstrap )
148
+ .withSocketOptions (socketOptions )
149
+ .withTlsContext (tlsContext )
150
+ .withUri (uri )
151
+ .withWindowSize (windowSize )
152
+ .withMaxConnections (maxConnectionsPerEndpoint );
153
+
154
+ return HttpClientConnectionManager .create (options );
140
155
}
141
156
142
157
private HttpClientConnectionManager getOrCreateConnectionPool (URI uri ) {
@@ -194,7 +209,7 @@ private HttpHeader[] asArray(List<HttpHeader> crtHeaderList) {
194
209
return crtHeaderList .toArray (new HttpHeader [crtHeaderList .size ()]);
195
210
}
196
211
197
- private HttpRequest toCrtRequest (URI uri , AsyncExecuteRequest asyncRequest ) {
212
+ private HttpRequest toCrtRequest (URI uri , AsyncExecuteRequest asyncRequest , AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter ) {
198
213
SdkHttpRequest sdkRequest = asyncRequest .request ();
199
214
Validate .notNull (uri , "URI must not be null" );
200
215
Validate .notNull (sdkRequest , "SdkHttpRequest must not be null" );
@@ -207,7 +222,7 @@ private HttpRequest toCrtRequest(URI uri, AsyncExecuteRequest asyncRequest) {
207
222
208
223
HttpHeader [] crtHeaderArray = asArray (createHttpHeaderList (uri , asyncRequest ));
209
224
210
- return new HttpRequest (method , encodedPath + encodedQueryString , crtHeaderArray );
225
+ return new HttpRequest (method , encodedPath + encodedQueryString , crtHeaderArray , crtToSdkAdapter );
211
226
}
212
227
213
228
@ Override
@@ -222,13 +237,12 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
222
237
223
238
URI uri = toUri (asyncRequest .request ());
224
239
HttpClientConnectionManager crtConnPool = getOrCreateConnectionPool (uri );
225
- HttpRequest crtRequest = toCrtRequest (uri , asyncRequest );
226
-
227
240
CompletableFuture <Void > requestFuture = new CompletableFuture <>();
228
241
229
242
// When a Connection is ready from the Connection Pool, schedule the Request on the connection
230
243
crtConnPool .acquireConnection ()
231
244
.whenComplete ((crtConn , throwable ) -> {
245
+
232
246
// If we didn't get a connection for some reason, fail the request
233
247
if (throwable != null ) {
234
248
requestFuture .completeExceptionally (throwable );
@@ -237,6 +251,7 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
237
251
238
252
AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter =
239
253
new AwsCrtAsyncHttpStreamAdapter (crtConn , requestFuture , asyncRequest , windowSize );
254
+ HttpRequest crtRequest = toCrtRequest (uri , asyncRequest , crtToSdkAdapter );
240
255
241
256
// Submit the Request on this Connection
242
257
invokeSafely (() -> crtConn .makeRequest (crtRequest , crtToSdkAdapter ));
@@ -263,24 +278,17 @@ public void close() {
263
278
*/
264
279
public interface Builder extends SdkAsyncHttpClient .Builder <AwsCrtAsyncHttpClient .Builder > {
265
280
266
- /**
267
- * The number of Threads to use in the EventLoop.
268
- * @param eventLoopSize The number of Threads to use in the EventLoop.
269
- * @return the builder of the method chaining.
270
- */
271
- Builder eventLoopSize (int eventLoopSize );
272
-
273
281
/**
274
282
* The AWS CRT TlsCipherPreference to use for this Client
275
283
* @param tlsCipherPreference The AWS Common Runtime TlsCipherPreference
276
- * @return the builder of the method chaining.
284
+ * @return The builder of the method chaining.
277
285
*/
278
286
Builder tlsCipherPreference (TlsCipherPreference tlsCipherPreference );
279
287
280
288
/**
281
289
* Whether or not to Verify the Peer's TLS Certificate Chain.
282
290
* @param verifyPeer true if the Certificate Chain should be validated, false if validation should be skipped.
283
- * @return the builder of the method chaining.
291
+ * @return The builder of the method chaining.
284
292
*/
285
293
Builder verifyPeer (boolean verifyPeer );
286
294
@@ -290,9 +298,23 @@ public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClien
290
298
* the Subscriber to read more data.
291
299
*
292
300
* @param windowSize The AWS Common Runtime WindowSize
293
- * @return the builder of the method chaining.
301
+ * @return The builder of the method chaining.
294
302
*/
295
303
Builder windowSize (int windowSize );
304
+
305
+ /**
306
+ * The AWS CRT EventLoopGroup to use for this Client.
307
+ * @param eventLoopGroup The AWS CRT EventLoopGroup to use for this client.
308
+ * @return The builder of the method chaining.
309
+ */
310
+ Builder eventLoopGroup (EventLoopGroup eventLoopGroup );
311
+
312
+ /**
313
+ * The AWS CRT HostResolver to use for this Client.
314
+ * @param hostResolver The AWS CRT HostResolver to use for this client.
315
+ * @return The builder of the method chaining.
316
+ */
317
+ Builder hostResolver (HostResolver hostResolver );
296
318
}
297
319
298
320
/**
@@ -301,10 +323,11 @@ public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClien
301
323
*/
302
324
private static final class DefaultBuilder implements Builder {
303
325
private final AttributeMap .Builder standardOptions = AttributeMap .builder ();
304
- private int eventLoopSize = Runtime .getRuntime ().availableProcessors ();
305
326
private TlsCipherPreference cipherPreference = TlsCipherPreference .TLS_CIPHER_SYSTEM_DEFAULT ;
306
327
private int windowSize = DEFAULT_STREAM_WINDOW_SIZE ;
307
328
private boolean verifyPeer = true ;
329
+ private EventLoopGroup eventLoopGroup ;
330
+ private HostResolver hostResolver ;
308
331
309
332
private DefaultBuilder () {
310
333
}
@@ -322,13 +345,6 @@ public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
322
345
.merge (SdkHttpConfigurationOption .GLOBAL_HTTP_DEFAULTS ));
323
346
}
324
347
325
- @ Override
326
- public Builder eventLoopSize (int eventLoopSize ) {
327
- Validate .isPositive (eventLoopSize , "eventLoopSize" );
328
- this .eventLoopSize = eventLoopSize ;
329
- return this ;
330
- }
331
-
332
348
@ Override
333
349
public Builder tlsCipherPreference (TlsCipherPreference tlsCipherPreference ) {
334
350
Validate .notNull (tlsCipherPreference , "cipherPreference" );
@@ -350,5 +366,17 @@ public Builder windowSize(int windowSize) {
350
366
this .windowSize = windowSize ;
351
367
return this ;
352
368
}
369
+
370
+ @ Override
371
+ public Builder eventLoopGroup (EventLoopGroup eventLoopGroup ) {
372
+ this .eventLoopGroup = eventLoopGroup ;
373
+ return this ;
374
+ }
375
+
376
+ @ Override
377
+ public Builder hostResolver (HostResolver hostResolver ) {
378
+ this .hostResolver = hostResolver ;
379
+ return this ;
380
+ }
353
381
}
354
382
}
0 commit comments