17
17
18
18
import static software .amazon .awssdk .utils .CollectionUtils .isNullOrEmpty ;
19
19
import static software .amazon .awssdk .utils .FunctionalUtils .invokeSafely ;
20
+ import static software .amazon .awssdk .utils .Validate .paramNotNull ;
20
21
21
22
import java .io .IOException ;
22
23
import java .net .URI ;
46
47
import software .amazon .awssdk .crt .io .TlsContext ;
47
48
import software .amazon .awssdk .crt .io .TlsContextOptions ;
48
49
import software .amazon .awssdk .http .Header ;
49
- import software .amazon .awssdk .http .SdkHttpClient ;
50
50
import software .amazon .awssdk .http .SdkHttpConfigurationOption ;
51
51
import software .amazon .awssdk .http .SdkHttpRequest ;
52
52
import software .amazon .awssdk .http .async .AsyncExecuteRequest ;
59
59
import software .amazon .awssdk .utils .http .SdkHttpUtils ;
60
60
61
61
/**
62
- * An implementation of {@link SdkHttpClient } that uses the AWS Common Runtime (CRT) Http Client to communicate with
62
+ * An implementation of {@link SdkAsyncHttpClient } that uses the AWS Common Runtime (CRT) Http Client to communicate with
63
63
* Http Web Services. This client is asynchronous and uses non-blocking IO.
64
64
*
65
65
* <p>This can be created via {@link #builder()}</p>
@@ -69,8 +69,6 @@ public final class AwsCrtAsyncHttpClient implements SdkAsyncHttpClient {
69
69
private static final Logger log = Logger .loggerFor (AwsCrtAsyncHttpClient .class );
70
70
71
71
private static final String AWS_COMMON_RUNTIME = "AwsCommonRuntime" ;
72
- private static final String NULL_REQUEST_ERROR_MESSAGE = "SdkHttpRequest must not be null" ;
73
- private static final String NULL_URI_ERROR_MESSAGE = "URI must not be null" ;
74
72
private static final int DEFAULT_STREAM_WINDOW_SIZE = 16 * 1024 * 1024 ; // 16 MB
75
73
76
74
private final Map <URI , HttpClientConnectionManager > connectionPools = new ConcurrentHashMap <>();
@@ -115,27 +113,28 @@ private AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
115
113
}
116
114
117
115
private HttpProxyOptions buildProxyOptions (ProxyConfiguration proxyConfiguration ) {
118
- if (proxyConfiguration != null ) {
119
- HttpProxyOptions clientProxyOptions = new HttpProxyOptions ();
116
+ if (proxyConfiguration == null ) {
117
+ return null ;
118
+ }
120
119
121
- clientProxyOptions .setHost (proxyConfiguration .host ());
122
- clientProxyOptions .setPort (proxyConfiguration .port ());
123
- if (proxyConfiguration .scheme () != null && proxyConfiguration .scheme ().equalsIgnoreCase ("https" )) {
124
- clientProxyOptions .setTlsContext (tlsContext );
125
- }
120
+ HttpProxyOptions clientProxyOptions = new HttpProxyOptions ();
126
121
127
- if (proxyConfiguration .username () != null && proxyConfiguration .password () != null ) {
128
- clientProxyOptions .setAuthorizationUsername (proxyConfiguration .username ());
129
- clientProxyOptions .setAuthorizationPassword (proxyConfiguration .password ());
130
- clientProxyOptions .setAuthorizationType (HttpProxyOptions .HttpProxyAuthorizationType .Basic );
131
- } else {
132
- clientProxyOptions .setAuthorizationType (HttpProxyOptions .HttpProxyAuthorizationType .None );
133
- }
122
+ clientProxyOptions .setHost (proxyConfiguration .host ());
123
+ clientProxyOptions .setPort (proxyConfiguration .port ());
124
+
125
+ if ("https" .equalsIgnoreCase (proxyConfiguration .scheme ())) {
126
+ clientProxyOptions .setTlsContext (tlsContext );
127
+ }
134
128
135
- return clientProxyOptions ;
129
+ if (proxyConfiguration .username () != null && proxyConfiguration .password () != null ) {
130
+ clientProxyOptions .setAuthorizationUsername (proxyConfiguration .username ());
131
+ clientProxyOptions .setAuthorizationPassword (proxyConfiguration .password ());
132
+ clientProxyOptions .setAuthorizationType (HttpProxyOptions .HttpProxyAuthorizationType .Basic );
136
133
} else {
137
- return null ;
134
+ clientProxyOptions . setAuthorizationType ( HttpProxyOptions . HttpProxyAuthorizationType . None ) ;
138
135
}
136
+
137
+ return clientProxyOptions ;
139
138
}
140
139
141
140
/**
@@ -154,7 +153,6 @@ private <T extends CrtResource> T registerOwnedResource(T subresource) {
154
153
}
155
154
156
155
private static URI toUri (SdkHttpRequest sdkRequest ) {
157
- Validate .notNull (sdkRequest , NULL_REQUEST_ERROR_MESSAGE );
158
156
return invokeSafely (() -> new URI (sdkRequest .protocol (), null , sdkRequest .host (), sdkRequest .port (),
159
157
null , null , null ));
160
158
}
@@ -202,7 +200,6 @@ private HttpClientConnectionManager createConnectionPool(URI uri) {
202
200
* pool implementation.
203
201
*/
204
202
private HttpClientConnectionManager getOrCreateConnectionPool (URI uri ) {
205
- Validate .notNull (uri , NULL_URI_ERROR_MESSAGE );
206
203
synchronized (this ) {
207
204
if (isClosed ) {
208
205
throw new IllegalStateException ("Client is closed. No more requests can be made with this client." );
@@ -247,13 +244,11 @@ private List<HttpHeader> createHttpHeaderList(URI uri, AsyncExecuteRequest async
247
244
}
248
245
249
246
private HttpHeader [] asArray (List <HttpHeader > crtHeaderList ) {
250
- return crtHeaderList .toArray (new HttpHeader [crtHeaderList . size () ]);
247
+ return crtHeaderList .toArray (new HttpHeader [0 ]);
251
248
}
252
249
253
250
private HttpRequest toCrtRequest (URI uri , AsyncExecuteRequest asyncRequest , AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter ) {
254
251
SdkHttpRequest sdkRequest = asyncRequest .request ();
255
- Validate .notNull (uri , NULL_URI_ERROR_MESSAGE );
256
- Validate .notNull (sdkRequest , NULL_REQUEST_ERROR_MESSAGE );
257
252
258
253
String method = sdkRequest .method ().name ();
259
254
String encodedPath = sdkRequest .encodedPath ();
@@ -273,10 +268,10 @@ private HttpRequest toCrtRequest(URI uri, AsyncExecuteRequest asyncRequest, AwsC
273
268
@ Override
274
269
public CompletableFuture <Void > execute (AsyncExecuteRequest asyncRequest ) {
275
270
276
- Validate . notNull (asyncRequest , "AsyncExecuteRequest must not be null " );
277
- Validate . notNull (asyncRequest .request (), NULL_REQUEST_ERROR_MESSAGE );
278
- Validate . notNull (asyncRequest .requestContentPublisher (), "RequestContentPublisher must not be null " );
279
- Validate . notNull (asyncRequest .responseHandler (), "ResponseHandler must not be null " );
271
+ paramNotNull (asyncRequest , "asyncRequest " );
272
+ paramNotNull (asyncRequest .request (), "SdkHttpRequest" );
273
+ paramNotNull (asyncRequest .requestContentPublisher (), "RequestContentPublisher" );
274
+ paramNotNull (asyncRequest .responseHandler (), "ResponseHandler" );
280
275
281
276
URI uri = toUri (asyncRequest .request ());
282
277
@@ -292,7 +287,6 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
292
287
*/
293
288
try (HttpClientConnectionManager crtConnPool = getOrCreateConnectionPool (uri )) {
294
289
CompletableFuture <Void > requestFuture = new CompletableFuture <>();
295
-
296
290
// When a Connection is ready from the Connection Pool, schedule the Request on the connection
297
291
crtConnPool .acquireConnection ()
298
292
.whenComplete ((crtConn , throwable ) -> {
@@ -301,23 +295,23 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
301
295
try {
302
296
asyncRequest .responseHandler ().onError (throwable );
303
297
} catch (Exception e ) {
304
- log .error (() -> String . format ( "Exception while handling error: %s " , e . toString ()) );
298
+ log .warn (() -> "Exception while handling error" , e );
305
299
}
306
300
requestFuture .completeExceptionally (new IOException (
307
301
"Crt exception while acquiring connection" , throwable ));
308
302
return ;
309
303
}
310
-
311
304
AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter =
312
305
new AwsCrtAsyncHttpStreamAdapter (crtConn , requestFuture , asyncRequest , initialWindowSize );
313
306
HttpRequest crtRequest = toCrtRequest (uri , asyncRequest , crtToSdkAdapter );
314
-
315
307
// Submit the Request on this Connection
316
308
invokeSafely (() -> {
317
309
try {
318
310
crtConn .makeRequest (crtRequest , crtToSdkAdapter ).activate ();
319
311
} catch (IllegalStateException | CrtRuntimeException e ) {
320
- throw new IOException ("Exception throw while submitting request to CRT http connection" , e );
312
+ log .error (() -> "Exception occurred when making the request" , e );
313
+ requestFuture .completeExceptionally (
314
+ new IOException ("Exception throw while submitting request to CRT http connection" , e ));
321
315
}
322
316
});
323
317
});
@@ -348,11 +342,11 @@ public void close() {
348
342
public interface Builder extends SdkAsyncHttpClient .Builder <AwsCrtAsyncHttpClient .Builder > {
349
343
350
344
/**
351
- * The maximum number of connections allowed per distinct endpoint
352
- * @param maxConnections maximum connections per endpoint
345
+ * The Maximum number of allowed concurrent requests. For HTTP/1.1 this is the same as max connections.
346
+ * @param maxConcurrency maximum concurrency per endpoint
353
347
* @return The builder of the method chaining.
354
348
*/
355
- Builder maxConnections (int maxConnections );
349
+ Builder maxConcurrency (int maxConcurrency );
356
350
357
351
/**
358
352
* The AWS CRT TlsCipherPreference to use for this Client
@@ -445,9 +439,9 @@ public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
445
439
}
446
440
447
441
@ Override
448
- public Builder maxConnections (int maxConnections ) {
449
- Validate .isPositive (maxConnections , "maxConnections " );
450
- standardOptions .put (SdkHttpConfigurationOption .MAX_CONNECTIONS , maxConnections );
442
+ public Builder maxConcurrency (int maxConcurrency ) {
443
+ Validate .isPositive (maxConcurrency , "maxConcurrency " );
444
+ standardOptions .put (SdkHttpConfigurationOption .MAX_CONNECTIONS , maxConcurrency );
451
445
return this ;
452
446
}
453
447
0 commit comments