diff --git a/crt/aws-c-http b/crt/aws-c-http index ce0d65623..e638eb004 160000 --- a/crt/aws-c-http +++ b/crt/aws-c-http @@ -1 +1 @@ -Subproject commit ce0d65623bff28f03204756d9d1b3366bd0b387d +Subproject commit e638eb00423029d422aea97fcfadeb68890a2f5c diff --git a/src/main/java/software/amazon/awssdk/crt/auth/credentials/CognitoCredentialsProvider.java b/src/main/java/software/amazon/awssdk/crt/auth/credentials/CognitoCredentialsProvider.java index 8b9b17d90..df27b6214 100644 --- a/src/main/java/software/amazon/awssdk/crt/auth/credentials/CognitoCredentialsProvider.java +++ b/src/main/java/software/amazon/awssdk/crt/auth/credentials/CognitoCredentialsProvider.java @@ -204,6 +204,7 @@ private CognitoCredentialsProvider(CognitoCredentialsProviderBuilder builder) { int proxyAuthorizationType = 0; String proxyAuthorizationUsername = null; String proxyAuthorizationPassword = null; + String noProxyHosts = null; HttpProxyOptions proxyOptions = builder.getHttpProxyOptions(); if (proxyOptions != null) { proxyConnectionType = proxyOptions.getConnectionType().getValue(); @@ -217,6 +218,9 @@ private CognitoCredentialsProvider(CognitoCredentialsProviderBuilder builder) { proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue(); proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername(); proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword(); + if (proxyOptions.getNoProxyHosts() != null) { + noProxyHosts = proxyOptions.getNoProxyHosts(); + } } long nativeHandle = cognitoCredentialsProviderNew( @@ -234,6 +238,7 @@ private CognitoCredentialsProvider(CognitoCredentialsProviderBuilder builder) { proxyAuthorizationType, proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null, proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null, + noProxyHosts != null ? noProxyHosts.getBytes(UTF8) : null, builder.loginTokenSource); acquireNativeHandle(nativeHandle); @@ -305,7 +310,8 @@ private static native long cognitoCredentialsProviderNew(CognitoCredentialsProvi int proxyAuthorizationType, byte[] proxyAuthorizationUsername, byte[] proxyAuthorizationPassword, - CognitoLoginTokenSource loginTokenSource); + byte[] noProxyHosts, + CognitoLoginTokenSource loginTokenSource); private static native void completeLoginTokenFetch(long invocationHandle, byte[] marshalledLogins, Throwable ex); } diff --git a/src/main/java/software/amazon/awssdk/crt/auth/credentials/X509CredentialsProvider.java b/src/main/java/software/amazon/awssdk/crt/auth/credentials/X509CredentialsProvider.java index 5d901c5c4..8b33c4cdf 100644 --- a/src/main/java/software/amazon/awssdk/crt/auth/credentials/X509CredentialsProvider.java +++ b/src/main/java/software/amazon/awssdk/crt/auth/credentials/X509CredentialsProvider.java @@ -155,6 +155,7 @@ private X509CredentialsProvider(X509CredentialsProviderBuilder builder) { int proxyAuthorizationType = 0; String proxyAuthorizationUsername = null; String proxyAuthorizationPassword = null; + String noProxyHosts = null; HttpProxyOptions proxyOptions = builder.getProxyOptions(); if (proxyOptions != null) { proxyConnectionType = proxyOptions.getConnectionType().getValue(); @@ -168,6 +169,7 @@ private X509CredentialsProvider(X509CredentialsProviderBuilder builder) { proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue(); proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername(); proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword(); + noProxyHosts = proxyOptions.getNoProxyHosts(); } long nativeHandle = x509CredentialsProviderNew( @@ -183,7 +185,8 @@ private X509CredentialsProvider(X509CredentialsProviderBuilder builder) { proxyTlsContextHandle, proxyAuthorizationType, proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null, - proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null); + proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null, + noProxyHosts != null ? noProxyHosts.getBytes(UTF8) : null); acquireNativeHandle(nativeHandle); addReferenceTo(clientBootstrap); @@ -206,5 +209,6 @@ private static native long x509CredentialsProviderNew(X509CredentialsProvider th long proxyTlsContext, int proxyAuthorizationType, byte[] proxyAuthorizationUsername, - byte[] proxyAuthorizationPassword); + byte[] proxyAuthorizationPassword, + byte[] noProxyHosts); } diff --git a/src/main/java/software/amazon/awssdk/crt/http/Http2StreamManager.java b/src/main/java/software/amazon/awssdk/crt/http/Http2StreamManager.java index 4c220286c..46e14da5c 100644 --- a/src/main/java/software/amazon/awssdk/crt/http/Http2StreamManager.java +++ b/src/main/java/software/amazon/awssdk/crt/http/Http2StreamManager.java @@ -78,6 +78,7 @@ private Http2StreamManager(Http2StreamManagerOptions options) { int proxyAuthorizationType = 0; String proxyAuthorizationUsername = null; String proxyAuthorizationPassword = null; + String noProxyHosts = null; HttpProxyOptions proxyOptions = connectionManagerOptions.getProxyOptions(); if (proxyOptions != null) { @@ -88,6 +89,7 @@ private Http2StreamManager(Http2StreamManagerOptions options) { proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue(); proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername(); proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword(); + noProxyHosts = proxyOptions.getNoProxyHosts(); } HttpMonitoringOptions monitoringOptions = connectionManagerOptions.getMonitoringOptions(); @@ -113,6 +115,7 @@ private Http2StreamManager(Http2StreamManagerOptions options) { proxyAuthorizationType, proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null, proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null, + noProxyHosts != null ? noProxyHosts.getBytes(UTF8) : null, connectionManagerOptions.isManualWindowManagement(), monitoringThroughputThresholdInBytesPerSecond, monitoringFailureIntervalInSeconds, @@ -254,6 +257,7 @@ private static native long http2StreamManagerNew(Http2StreamManager thisObj, int proxyAuthorizationType, byte[] proxyAuthorizationUsername, byte[] proxyAuthorizationPassword, + byte[] noProxyHosts, boolean isManualWindowManagement, long monitoringThroughputThresholdInBytesPerSecond, int monitoringFailureIntervalInSeconds, diff --git a/src/main/java/software/amazon/awssdk/crt/http/HttpClientConnectionManager.java b/src/main/java/software/amazon/awssdk/crt/http/HttpClientConnectionManager.java index 777bf629a..dac62ece5 100644 --- a/src/main/java/software/amazon/awssdk/crt/http/HttpClientConnectionManager.java +++ b/src/main/java/software/amazon/awssdk/crt/http/HttpClientConnectionManager.java @@ -78,6 +78,7 @@ private HttpClientConnectionManager(HttpClientConnectionManagerOptions options) int proxyAuthorizationType = 0; String proxyAuthorizationUsername = null; String proxyAuthorizationPassword = null; + String noProxyHosts = null; if (proxyOptions != null) { proxyConnectionType = proxyOptions.getConnectionType().getValue(); @@ -87,6 +88,7 @@ private HttpClientConnectionManager(HttpClientConnectionManagerOptions options) proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue(); proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername(); proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword(); + noProxyHosts = proxyOptions.getNoProxyHosts(); } int environmentVariableProxyConnectionType = 0; @@ -123,6 +125,7 @@ private HttpClientConnectionManager(HttpClientConnectionManagerOptions options) proxyAuthorizationType, proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null, proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null, + noProxyHosts != null ? noProxyHosts.getBytes(UTF8) : null, environmentVariableProxyConnectionType, environmentVariableProxyTlsConnectionOptions != null ? environmentVariableProxyTlsConnectionOptions.getNativeHandle() @@ -259,6 +262,7 @@ private static native long httpClientConnectionManagerNew(HttpClientConnectionMa int proxyAuthorizationType, byte[] proxyAuthorizationUsername, byte[] proxyAuthorizationPassword, + byte[] noProxyHosts, int environmentVariableProxyConnectionType, long environmentVariableProxyTlsConnectionOptions, int environmentVariableSetting, diff --git a/src/main/java/software/amazon/awssdk/crt/http/HttpProxyOptions.java b/src/main/java/software/amazon/awssdk/crt/http/HttpProxyOptions.java index 0e11f30de..35be0bc28 100644 --- a/src/main/java/software/amazon/awssdk/crt/http/HttpProxyOptions.java +++ b/src/main/java/software/amazon/awssdk/crt/http/HttpProxyOptions.java @@ -19,6 +19,7 @@ public class HttpProxyOptions { private TlsContext tlsContext; private HttpProxyAuthorizationType authorizationType; private HttpProxyConnectionType connectionType; + private String noProxyHosts; /** * what kind of authentication, if any, to use when connecting to a proxy server @@ -182,4 +183,24 @@ public void setTlsContext(TlsContext tlsContext) { */ public TlsContext getTlsContext() { return tlsContext; } + /** + * @return the nonProxyHosts setting for the proxy connection. + */ + public String getNoProxyHosts() { + return noProxyHosts; + } + + /** + * Sets the list of hosts for which not to use a proxy. This should be a comma seperated list + * of domain names, host names, or IP Addresses following the format used by CURL. + * The only wildcard available is a single "*" character, which matches all hosts, + * and effectively disables the proxy. + * IP addresses specified to this option can be provided using CIDR notation: an appended slash and number + * specifies the number of "network bits" out of the address to use in the comparison. + * + * @param noProxyHosts comma seperated list of hosts to skip proxy for. + */ + public void setNoProxyHosts(String noProxyHosts) { + this.noProxyHosts = noProxyHosts; + } } diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java index c7016dc03..c4ac6af1f 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java @@ -187,7 +187,8 @@ private void SetupConfig(MqttConnectionConfig config) throws MqttException { proxyTlsContext != null ? proxyTlsContext.getNativeHandle() : 0, options.getAuthorizationType().getValue(), options.getAuthorizationUsername(), - options.getAuthorizationPassword()); + options.getAuthorizationPassword(), + options.getNoProxyHosts()); } addReferenceTo(config); @@ -518,7 +519,8 @@ private static native void mqttClientConnectionSetHttpProxyOptions(long connecti long proxyTlsContext, int proxyAuthorizationType, String proxyAuthorizationUsername, - String proxyAuthorizationPassword) throws CrtRuntimeException; + String proxyAuthorizationPassword, + String noProxyHosts) throws CrtRuntimeException; private static native MqttClientConnectionOperationStatistics mqttClientConnectionGetOperationStatistics( long connection); diff --git a/src/main/java/software/amazon/awssdk/crt/s3/S3Client.java b/src/main/java/software/amazon/awssdk/crt/s3/S3Client.java index 4264741b8..4009961da 100644 --- a/src/main/java/software/amazon/awssdk/crt/s3/S3Client.java +++ b/src/main/java/software/amazon/awssdk/crt/s3/S3Client.java @@ -38,6 +38,7 @@ public S3Client(S3ClientOptions options) throws CrtRuntimeException { int proxyAuthorizationType = 0; String proxyAuthorizationUsername = null; String proxyAuthorizationPassword = null; + String noProxyHosts = null; // Handle FileIoOptions from S3ClientOptions boolean fioOptionsSet = false; boolean shouldStream = false; @@ -61,6 +62,7 @@ public S3Client(S3ClientOptions options) throws CrtRuntimeException { proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue(); proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername(); proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword(); + noProxyHosts = proxyOptions.getNoProxyHosts(); } int environmentVariableProxyConnectionType = 0; @@ -108,6 +110,7 @@ public S3Client(S3ClientOptions options) throws CrtRuntimeException { proxyAuthorizationType, proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null, proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null, + noProxyHosts != null ? noProxyHosts.getBytes(UTF8) : null, environmentVariableProxyConnectionType, environmentVariableProxyTlsConnectionOptions != null ? environmentVariableProxyTlsConnectionOptions.getNativeHandle() @@ -267,6 +270,7 @@ private static native long s3ClientNew(S3Client thisObj, byte[] region, long cli int proxyAuthorizationType, byte[] proxyAuthorizationUsername, byte[] proxyAuthorizationPassword, + byte[] noProxyHosts, int environmentVariableProxyConnectionType, long environmentVariableProxyTlsConnectionOptions, int environmentVariableSetting, diff --git a/src/native/credentials_provider.c b/src/native/credentials_provider.c index 6d778e0ae..a15458f05 100644 --- a/src/native/credentials_provider.c +++ b/src/native/credentials_provider.c @@ -429,7 +429,8 @@ JNIEXPORT jlong JNICALL jlong jni_proxy_tls_context, jint jni_proxy_authorization_type, jbyteArray jni_proxy_authorization_username, - jbyteArray jni_proxy_authorization_password) { + jbyteArray jni_proxy_authorization_password, + jbyteArray jni_no_proxy_hosts) { (void)jni_class; (void)env; @@ -471,6 +472,7 @@ JNIEXPORT jlong JNICALL jni_proxy_port, jni_proxy_authorization_username, jni_proxy_authorization_password, + jni_no_proxy_hosts, jni_proxy_authorization_type, (struct aws_tls_ctx *)jni_proxy_tls_context); @@ -491,7 +493,12 @@ JNIEXPORT jlong JNICALL aws_jni_byte_cursor_from_jbyteArray_release(env, endpoint, options.endpoint); aws_http_proxy_options_jni_clean_up( - env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password); + env, + &proxy_options, + jni_proxy_host, + jni_proxy_authorization_username, + jni_proxy_authorization_password, + jni_no_proxy_hosts); aws_tls_connection_options_clean_up(&tls_connection_options); @@ -929,6 +936,7 @@ jlong JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CognitoCredential jint proxy_authorization_type, jbyteArray proxy_authorization_username, jbyteArray proxy_authorization_password, + jbyteArray no_proxy_hosts, jobject login_token_source) { (void)jni_class; @@ -1015,6 +1023,7 @@ jlong JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CognitoCredential proxy_port, proxy_authorization_username, proxy_authorization_password, + no_proxy_hosts, proxy_authorization_type, (struct aws_tls_ctx *)native_proxy_tls_context); @@ -1034,7 +1043,7 @@ jlong JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CognitoCredential aws_jni_byte_cursor_from_jbyteArray_release(env, marshalled_logins, logins_cursor); aws_http_proxy_options_jni_clean_up( - env, &proxy_options, proxy_host, proxy_authorization_username, proxy_authorization_password); + env, &proxy_options, proxy_host, proxy_authorization_username, proxy_authorization_password, no_proxy_hosts); aws_array_list_clean_up(&logins); diff --git a/src/native/http2_stream_manager.c b/src/native/http2_stream_manager.c index b3765b1dd..c8a7a99b3 100644 --- a/src/native/http2_stream_manager.c +++ b/src/native/http2_stream_manager.c @@ -106,6 +106,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_Http2StreamManager_ jint jni_proxy_authorization_type, jbyteArray jni_proxy_authorization_username, jbyteArray jni_proxy_authorization_password, + jbyteArray jni_no_proxy_hosts, jboolean jni_manual_window_management, jlong jni_monitoring_throughput_threshold_in_bytes_per_second, jint jni_monitoring_failure_interval_in_seconds, @@ -233,6 +234,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_Http2StreamManager_ jni_proxy_port, jni_proxy_authorization_username, jni_proxy_authorization_password, + jni_no_proxy_hosts, jni_proxy_authorization_type, (struct aws_tls_ctx *)jni_proxy_tls_context); @@ -246,7 +248,12 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_Http2StreamManager_ } aws_http_proxy_options_jni_clean_up( - env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password); + env, + &proxy_options, + jni_proxy_host, + jni_proxy_authorization_username, + jni_proxy_authorization_password, + jni_no_proxy_hosts); if (new_tls_conn_opts) { aws_tls_connection_options_clean_up(&tls_conn_options); diff --git a/src/native/http_connection_manager.c b/src/native/http_connection_manager.c index eec6a3633..5496c5728 100644 --- a/src/native/http_connection_manager.c +++ b/src/native/http_connection_manager.c @@ -108,6 +108,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_HttpClientConnectio jint jni_proxy_authorization_type, jbyteArray jni_proxy_authorization_username, jbyteArray jni_proxy_authorization_password, + jbyteArray jni_no_proxy_hosts, jint jni_environment_variable_proxy_connection_type, jlong jni_environment_variable_proxy_tls_connection_options, jint jni_environment_variable_type, @@ -220,6 +221,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_HttpClientConnectio jni_proxy_port, jni_proxy_authorization_username, jni_proxy_authorization_password, + jni_no_proxy_hosts, jni_proxy_authorization_type, (struct aws_tls_ctx *)jni_proxy_tls_context); @@ -245,7 +247,12 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_HttpClientConnectio } aws_http_proxy_options_jni_clean_up( - env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password); + env, + &proxy_options, + jni_proxy_host, + jni_proxy_authorization_username, + jni_proxy_authorization_password, + jni_no_proxy_hosts); if (new_tls_conn_opts) { aws_tls_connection_options_clean_up(&tls_conn_options); diff --git a/src/native/http_proxy_options.c b/src/native/http_proxy_options.c index 22cd56645..860de6354 100644 --- a/src/native/http_proxy_options.c +++ b/src/native/http_proxy_options.c @@ -33,6 +33,7 @@ void aws_http_proxy_options_jni_init( jint proxy_port, jbyteArray proxy_authorization_username, jbyteArray proxy_authorization_password, + jbyteArray no_proxy_hosts, int proxy_authorization_type, struct aws_tls_ctx *proxy_tls_ctx) { @@ -54,6 +55,10 @@ void aws_http_proxy_options_jni_init( options->auth_password = aws_jni_byte_cursor_from_jbyteArray_acquire(env, proxy_authorization_password); } + if (no_proxy_hosts != NULL) { + options->no_proxy_hosts = aws_jni_byte_cursor_from_jbyteArray_acquire(env, no_proxy_hosts); + } + if (proxy_tls_ctx != NULL) { aws_tls_connection_options_init_from_ctx(tls_options, proxy_tls_ctx); aws_tls_connection_options_set_server_name(tls_options, allocator, &options->host); @@ -66,7 +71,8 @@ void aws_http_proxy_options_jni_clean_up( struct aws_http_proxy_options *options, jbyteArray proxy_host, jbyteArray proxy_authorization_username, - jbyteArray proxy_authorization_password) { + jbyteArray proxy_authorization_password, + jbyteArray no_proxy_hosts) { if (options->host.ptr != NULL) { aws_jni_byte_cursor_from_jbyteArray_release(env, proxy_host, options->host); @@ -80,6 +86,10 @@ void aws_http_proxy_options_jni_clean_up( aws_jni_byte_cursor_from_jbyteArray_release(env, proxy_authorization_password, options->auth_password); } + if (options->no_proxy_hosts.ptr != NULL) { + aws_jni_byte_cursor_from_jbyteArray_release(env, no_proxy_hosts, options->no_proxy_hosts); + } + if (options->tls_options != NULL) { aws_tls_connection_options_clean_up((struct aws_tls_connection_options *)options->tls_options); } diff --git a/src/native/http_proxy_options.h b/src/native/http_proxy_options.h index 1e2f29c5b..386c6e6c5 100644 --- a/src/native/http_proxy_options.h +++ b/src/native/http_proxy_options.h @@ -21,6 +21,7 @@ void aws_http_proxy_options_jni_init( jint proxy_port, jbyteArray proxy_authorization_username, jbyteArray proxy_authorization_password, + jbyteArray no_proxy_hosts, int proxy_authorization_type, struct aws_tls_ctx *proxy_tls_ctx); @@ -29,6 +30,7 @@ void aws_http_proxy_options_jni_clean_up( struct aws_http_proxy_options *options, jbyteArray proxy_host, jbyteArray proxy_authorization_username, - jbyteArray proxy_authorization_password); + jbyteArray proxy_authorization_password, + jbyteArray no_proxy_hosts); #endif /* AWS_JNI_CRT_HTTP_PROXY_OPTIONS_H */ diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index c143f2a68..5de927a71 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -1284,7 +1284,8 @@ void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClien jlong jni_proxy_tls_context, jint jni_proxy_authorization_type, jstring jni_proxy_authorization_username, - jstring jni_proxy_authorization_password) { + jstring jni_proxy_authorization_password, + jstring jni_no_proxy_hosts) { (void)jni_class; aws_cache_jni_ids(env); @@ -1314,6 +1315,10 @@ void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClien proxy_options.auth_password = aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_authorization_password); } + if (jni_no_proxy_hosts) { + proxy_options.no_proxy_hosts = aws_jni_byte_cursor_from_jstring_acquire(env, jni_no_proxy_hosts); + } + struct aws_tls_connection_options proxy_tls_conn_options; AWS_ZERO_STRUCT(proxy_tls_conn_options); @@ -1337,6 +1342,10 @@ void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClien aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_authorization_username, proxy_options.auth_username); } + if (jni_no_proxy_hosts) { + aws_jni_byte_cursor_from_jstring_release(env, jni_no_proxy_hosts, proxy_options.no_proxy_hosts); + } + aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_host, proxy_options.host); aws_tls_connection_options_clean_up(&proxy_tls_conn_options); } diff --git a/src/native/s3_client.c b/src/native/s3_client.c index e34130222..ed4aba252 100644 --- a/src/native/s3_client.c +++ b/src/native/s3_client.c @@ -336,6 +336,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_s3_S3Client_s3ClientNew( jint jni_proxy_authorization_type, jbyteArray jni_proxy_authorization_username, jbyteArray jni_proxy_authorization_password, + jbyteArray jni_proxy_no_proxy_hosts, jint jni_environment_variable_proxy_connection_type, jlong jni_environment_variable_proxy_tls_connection_options, jint jni_environment_variable_type, @@ -497,6 +498,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_s3_S3Client_s3ClientNew( jni_proxy_port, jni_proxy_authorization_username, jni_proxy_authorization_password, + jni_proxy_no_proxy_hosts, jni_proxy_authorization_type, (struct aws_tls_ctx *)jni_proxy_tls_context); @@ -529,7 +531,12 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_s3_S3Client_s3ClientNew( aws_jni_byte_cursor_from_jbyteArray_release(env, jni_region, region); aws_http_proxy_options_jni_clean_up( - env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password); + env, + &proxy_options, + jni_proxy_host, + jni_proxy_authorization_username, + jni_proxy_authorization_password, + jni_proxy_no_proxy_hosts); aws_mem_release(aws_jni_get_allocator(), s3_tcp_keep_alive_options); if (tls_options) { diff --git a/src/test/java/software/amazon/awssdk/crt/test/HttpClientConnectionTest.java b/src/test/java/software/amazon/awssdk/crt/test/HttpClientConnectionTest.java index fd59e20aa..9bd758409 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/HttpClientConnectionTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/HttpClientConnectionTest.java @@ -5,7 +5,9 @@ package software.amazon.awssdk.crt.test; +import java.util.Arrays; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Assume; @@ -15,6 +17,7 @@ import software.amazon.awssdk.crt.http.HttpClientConnectionManager; import software.amazon.awssdk.crt.http.HttpClientConnectionManagerOptions; import software.amazon.awssdk.crt.http.HttpException; +import software.amazon.awssdk.crt.http.HttpProxyOptions; import software.amazon.awssdk.crt.io.ClientBootstrap; import software.amazon.awssdk.crt.io.EventLoopGroup; import software.amazon.awssdk.crt.io.HostResolver; @@ -149,4 +152,55 @@ public void testRetryableErrorCheck() { exception = new HttpException(0x080a); assertTrue(HttpClientConnection.isErrorRetryable(exception)); } + + + /** + * This test exercises the noProxyHosts configuration. It is included here + * rather than in ProxyTests because a successful test connects to the configured + * endpoint and NOT the proxy host as expected in ProxyTests. + */ + @Test + public void testProxyOptionsNoProxyHosts() throws Exception { + skipIfAndroid(); + skipIfNetworkUnavailable(); + + URI uriMatchesNoProxyHost = new URI("https://aws-crt-test-stuff.s3.amazonaws.com"); + URI uriDoesNotMatchNoProxyHost = new URI("https://non-matching.amazon.com"); + try (ClientBootstrap bootstrap = new ClientBootstrap(null, null); + SocketOptions socketOptions = new SocketOptions(); + TlsContextOptions tlsOpts = TlsContextOptions.createDefaultClient(); + TlsContext tlsCtx = new TlsContext(tlsOpts)) { + + HttpClientConnectionManagerOptions options = new HttpClientConnectionManagerOptions(); + HttpProxyOptions proxyOptions = new HttpProxyOptions(); + // test will fail if noProxyHosts isn't applied and we try to connect with the proxy. + proxyOptions.setHost("unused-proxy-host.invalid"); + proxyOptions.setPort(443); + proxyOptions.setNoProxyHosts("s3.amazonaws.com"); + options.withProxyOptions(proxyOptions); + + // test connecting to a uri that matches, expect successful connection + options.withClientBootstrap(bootstrap).withSocketOptions(socketOptions).withTlsContext(tlsCtx).withUri(uriMatchesNoProxyHost); + try (HttpClientConnectionManager connectionPool = HttpClientConnectionManager.create(options)) { + try (HttpClientConnection conn = connectionPool.acquireConnection().get(60, TimeUnit.SECONDS)) { + ; + // connection succeeds, expect no errors + } + } + + // test connecting to a host that does not match the noProxyHosts + // expect failure to connect to invalid proxy + try { + options.withUri(uriDoesNotMatchNoProxyHost); + try (HttpClientConnectionManager connectionPool = HttpClientConnectionManager.create(options)) { + try (HttpClientConnection conn = connectionPool.acquireConnection().get(60, TimeUnit.SECONDS)) { + Assert.fail("Expected an exception"); + } + } + } catch (ExecutionException e) { + Assert.assertTrue(e.getCause() instanceof HttpException); + Assert.assertTrue(e.getMessage().contains("Host name was invalid")); + } + } + } } diff --git a/src/test/java/software/amazon/awssdk/crt/test/ProxyTest.java b/src/test/java/software/amazon/awssdk/crt/test/ProxyTest.java index ba164176b..d593aa8bc 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/ProxyTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/ProxyTest.java @@ -5,6 +5,7 @@ package software.amazon.awssdk.crt.test; +import java.util.concurrent.ExecutionException; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; @@ -16,6 +17,7 @@ import software.amazon.awssdk.crt.auth.credentials.X509CredentialsProvider; import software.amazon.awssdk.crt.http.HttpClientConnectionManager; import software.amazon.awssdk.crt.http.HttpClientConnectionManagerOptions; +import software.amazon.awssdk.crt.http.HttpException; import software.amazon.awssdk.crt.http.HttpHeader; import software.amazon.awssdk.crt.http.HttpProxyOptions; import software.amazon.awssdk.crt.http.HttpRequest; @@ -40,6 +42,8 @@ /* For environment variable setup, see SetupCrossCICrtEnvironment in the CRT builder */ public class ProxyTest extends CrtTestFixture { + public static final int CRT_ERROR_CODE_DNS_INVALID_NAME = 1059; + enum ProxyTestType { FORWARDING, TUNNELING_HTTP, @@ -47,6 +51,7 @@ enum ProxyTestType { TUNNELING_DOUBLE_TLS, LEGACY_HTTP, LEGACY_HTTPS, + PROXY_DISABLED_NO_PROXY_HOSTS } enum ProxyAuthType { @@ -138,6 +143,8 @@ private URI getUriForTest(ProxyTestType testType) { case TUNNELING_DOUBLE_TLS: case LEGACY_HTTPS: return new URI("https://s3.amazonaws.com"); + case PROXY_DISABLED_NO_PROXY_HOSTS: + return new URI("https://host-does-not-exist.invalid"); default: return new URI("http://www.example.com"); @@ -173,6 +180,9 @@ private HttpProxyOptions buildProxyOptions(ProxyTestType testType, ProxyAuthType proxyOptions.setAuthorizationUsername(HTTP_PROXY_BASIC_AUTH_USERNAME); proxyOptions.setAuthorizationPassword(HTTP_PROXY_BASIC_AUTH_PASSWORD); } + if (testType == ProxyTestType.PROXY_DISABLED_NO_PROXY_HOSTS) { + proxyOptions.setNoProxyHosts("host-does-not-exist.invalid"); + } return proxyOptions; } @@ -349,6 +359,21 @@ public void testConnectionManager_TunnelingHttpsProxy_BasicAuth() { } } + @Test + public void testConnectionManager_noProxyHosts() { + skipIfNetworkUnavailable(); + Assume.assumeTrue(isEnvironmentSetUpForProxyTests()); + + try (HttpClientConnectionManager manager = buildProxiedConnectionManager(ProxyTestType.PROXY_DISABLED_NO_PROXY_HOSTS, ProxyAuthType.None)) { + doHttpConnectionManagerProxyTest(manager); + Assert.fail("Expected exception"); + } catch (Exception e) { + // unable to connect to the non-proxy host, expect dns failure + Assert.assertTrue(e.getCause() instanceof HttpException); + Assert.assertTrue(e.getMessage().contains("Host name was invalid")); + } + } + private void doCredentialsProviderProxyTest(CredentialsProvider provider) { try { Credentials credentials = provider.getCredentials().get();