diff --git a/README.md b/README.md
index 7c7e65356..55a659f1b 100644
--- a/README.md
+++ b/README.md
@@ -159,8 +159,8 @@ The following table lists all valid connection properties:
| TOKEN | Depends | The OAuth token to use for OAuth authentication. Must be used in combination with AUTHENTICATOR=oauth. |
| INSECUREMODE | No | Set to true to disable the certificate revocation list check. Default is false. |
| USEPROXY | No | Set to true if you need to use a proxy server. The default value is false.
This parameter was introduced in v2.0.4. |
-| PROXYHOST | Depends | The hostname of the proxy server.
If USEPROXY is set to `true`, you must set this parameter.
This parameter was introduced in v2.0.4. |
-| PROXYPORT | Depends | The port number of the proxy server.
If USEPROXY is set to `true`, you must set this parameter.
This parameter was introduced in v2.0.4. |
+| PROXYHOST | No | The hostname of the proxy server.
If USEPROXY is set to `true`, you can set this parameter to define the proxy explicitly. If not set, the default proxy will be used (HTTPS_PROXY, WinINet...).
This parameter was introduced in v2.0.4. |
+| PROXYPORT | Depends | The port number of the proxy server.
If USEPROXY is set to `true` and PROXYHOST is specfied, you must set this parameter.
This parameter was introduced in v2.0.4. |
| PROXYUSER | No | The username for authenticating to the proxy server.
This parameter was introduced in v2.0.4. |
| PROXYPASSWORD | Depends | The password for authenticating to the proxy server.
If USEPROXY is `true` and PROXYUSER is set, you must set this parameter.
This parameter was introduced in v2.0.4. |
| NONPROXYHOSTS | No | The list of hosts that the driver should connect to directly, bypassing the proxy server. Separate the hostnames with a pipe symbol (\|). You can also use an asterisk (`*`) as a wildcard.
The host target value should fully match with any item from the proxy host list to bypass the proxy server.
This parameter was introduced in v2.0.4. |
diff --git a/Snowflake.Data.Tests/SFBaseTest.cs b/Snowflake.Data.Tests/SFBaseTest.cs
index 6aacb94f9..711960007 100755
--- a/Snowflake.Data.Tests/SFBaseTest.cs
+++ b/Snowflake.Data.Tests/SFBaseTest.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2012-2021 Snowflake Computing Inc. All rights reserved.
*/
diff --git a/Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs b/Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs
index 668db5f91..911716a91 100644
--- a/Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs
+++ b/Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2022 Snowflake Computing Inc. All rights reserved.
*/
@@ -102,48 +102,75 @@ public void TestGetJitter(int seconds)
}
[Test]
- public void ShouldCreateHttpClientHandlerWithProxy()
+ public void ShouldCreateHttpClientHandlerWithExplicitProxy()
{
// given
var config = new HttpClientConfig(
+ true,
true,
"snowflake.com",
"123",
"testUser",
"proxyPassword",
- "localhost",
+ "localhost",
false,
false,
7
);
-
+
// when
var handler = (HttpClientHandler) HttpUtil.Instance.SetupCustomHttpHandler(config);
-
+
// then
Assert.IsTrue(handler.UseProxy);
Assert.IsNotNull(handler.Proxy);
}
[Test]
- public void ShouldCreateHttpClientHandlerWithoutProxy()
+ public void ShouldCreateHttpClientHandlerWithImplicitProxy()
{
// given
var config = new HttpClientConfig(
+ true,
true,
null,
null,
null,
null,
- null,
+ null,
+ false,
+ false,
+ 7
+ );
+
+ // when
+ var handler = (HttpClientHandler) HttpUtil.Instance.SetupCustomHttpHandler(config);
+
+ // then
+ Assert.IsTrue(handler.UseProxy);
+ Assert.IsNull(handler.Proxy);
+ }
+
+ [Test]
+ public void ShouldCreateHttpClientHandlerWithoutProxy()
+ {
+ // given
+ var config = new HttpClientConfig(
+ false,
+ false,
+ null,
+ null,
+ null,
+ null,
+ null,
false,
false,
0
);
-
+
// when
var handler = (HttpClientHandler) HttpUtil.Instance.SetupCustomHttpHandler(config);
-
+
// then
Assert.IsFalse(handler.UseProxy);
Assert.IsNull(handler.Proxy);
diff --git a/Snowflake.Data/Core/HttpUtil.cs b/Snowflake.Data/Core/HttpUtil.cs
index 531e76fd7..f7a2cd2f9 100755
--- a/Snowflake.Data/Core/HttpUtil.cs
+++ b/Snowflake.Data/Core/HttpUtil.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2012-2021 Snowflake Computing Inc. All rights reserved.
*/
@@ -21,6 +21,7 @@ public class HttpClientConfig
{
public HttpClientConfig(
bool crlCheckEnabled,
+ bool useProxy,
string proxyHost,
string proxyPort,
string proxyUser,
@@ -32,6 +33,7 @@ public HttpClientConfig(
bool includeRetryReason = true)
{
CrlCheckEnabled = crlCheckEnabled;
+ UseProxy = useProxy;
ProxyHost = proxyHost;
ProxyPort = proxyPort;
ProxyUser = proxyUser;
@@ -45,6 +47,7 @@ public HttpClientConfig(
ConfKey = string.Join(";",
new string[] {
crlCheckEnabled.ToString(),
+ useProxy.ToString(),
proxyHost,
proxyPort,
proxyUser,
@@ -57,6 +60,7 @@ public HttpClientConfig(
}
public readonly bool CrlCheckEnabled;
+ public readonly bool UseProxy;
public readonly string ProxyHost;
public readonly string ProxyPort;
public readonly string ProxyUser;
@@ -87,7 +91,7 @@ public sealed class HttpUtil
private HttpUtil()
{
- // This value is used by AWS SDK and can cause deadlock,
+ // This value is used by AWS SDK and can cause deadlock,
// so we need to increase the default value of 2
// See: https://github.com/aws/aws-sdk-net/issues/152
ServicePointManager.DefaultConnectionLimit = 50;
@@ -130,7 +134,7 @@ private HttpClient RegisterNewHttpClientIfNecessary(HttpClientConfig config)
internal HttpMessageHandler SetupCustomHttpHandler(HttpClientConfig config)
{
- HttpMessageHandler httpHandler;
+ HttpClientHandler httpHandler;
try
{
httpHandler = new HttpClientHandler()
@@ -140,8 +144,7 @@ internal HttpMessageHandler SetupCustomHttpHandler(HttpClientConfig config)
// Enforce tls v1.2
SslProtocols = SslProtocols.Tls12,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
- UseCookies = false, // Disable cookies
- UseProxy = false
+ UseCookies = false // Disable cookies
};
}
// special logic for .NET framework 4.7.1 that
@@ -151,56 +154,62 @@ internal HttpMessageHandler SetupCustomHttpHandler(HttpClientConfig config)
httpHandler = new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
- UseCookies = false, // Disable cookies
- UseProxy = false
+ UseCookies = false // Disable cookies
};
}
// Add a proxy if necessary
- if (null != config.ProxyHost)
+ if (!config.UseProxy)
+ {
+ httpHandler.UseProxy = false;
+ }
+ else
{
// Proxy needed
- WebProxy proxy = new WebProxy(config.ProxyHost, int.Parse(config.ProxyPort));
+ httpHandler.UseProxy = true;
- // Add credential if provided
- if (!String.IsNullOrEmpty(config.ProxyUser))
+ if (!String.IsNullOrEmpty(config.ProxyHost))
{
- ICredentials credentials = new NetworkCredential(config.ProxyUser, config.ProxyPassword);
- proxy.Credentials = credentials;
- }
+ // Host explicitly specified, do not use default proxy
+ WebProxy proxy = new WebProxy(config.ProxyHost, int.Parse(config.ProxyPort));
- // Add bypasslist if provided
- if (!String.IsNullOrEmpty(config.NoProxyList))
- {
- string[] bypassList = config.NoProxyList.Split(
- new char[] { '|' },
- StringSplitOptions.RemoveEmptyEntries);
- // Convert simplified syntax to standard regular expression syntax
- string entry = null;
- for (int i = 0; i < bypassList.Length; i++)
+ // Add credential if provided
+ if (!String.IsNullOrEmpty(config.ProxyUser))
+ {
+ ICredentials credentials = new NetworkCredential(config.ProxyUser, config.ProxyPassword);
+ proxy.Credentials = credentials;
+ }
+
+ // Add bypasslist if provided
+ if (!String.IsNullOrEmpty(config.NoProxyList))
{
- // Get the original entry
- entry = bypassList[i].Trim();
- // . -> [.] because . means any char
- entry = entry.Replace(".", "[.]");
- // * -> .* because * is a quantifier and need a char or group to apply to
- entry = entry.Replace("*", ".*");
-
- entry = entry.StartsWith("^") ? entry : $"^{entry}";
-
- entry = entry.EndsWith("$") ? entry : $"{entry}$";
-
- // Replace with the valid entry syntax
- bypassList[i] = entry;
+ string[] bypassList = config.NoProxyList.Split(
+ new char[] { '|' },
+ StringSplitOptions.RemoveEmptyEntries);
+ // Convert simplified syntax to standard regular expression syntax
+ string entry = null;
+ for (int i = 0; i < bypassList.Length; i++)
+ {
+ // Get the original entry
+ entry = bypassList[i].Trim();
+ // . -> [.] because . means any char
+ entry = entry.Replace(".", "[.]");
+ // * -> .* because * is a quantifier and need a char or group to apply to
+ entry = entry.Replace("*", ".*");
+
+ entry = entry.StartsWith("^") ? entry : $"^{entry}";
+
+ entry = entry.EndsWith("$") ? entry : $"{entry}$";
+
+ // Replace with the valid entry syntax
+ bypassList[i] = entry;
+ }
+ proxy.BypassList = bypassList;
}
- proxy.BypassList = bypassList;
- }
- HttpClientHandler httpHandlerWithProxy = (HttpClientHandler)httpHandler;
- httpHandlerWithProxy.UseProxy = true;
- httpHandlerWithProxy.Proxy = proxy;
- return httpHandlerWithProxy;
+ httpHandler.Proxy = proxy;
+ }
}
return httpHandler;
}
@@ -384,7 +393,7 @@ protected override async Task SendAsync(HttpRequestMessage
if (httpTimeout.Ticks == 0)
childCts.Cancel();
else
- childCts.CancelAfter(httpTimeout);
+ childCts.CancelAfter(httpTimeout);
}
response = await base.SendAsync(requestMessage, childCts == null ?
cancellationToken : childCts.Token).ConfigureAwait(false);
diff --git a/Snowflake.Data/Core/Session/SFSessionHttpClientProperties.cs b/Snowflake.Data/Core/Session/SFSessionHttpClientProperties.cs
index f129de25a..abe08554c 100644
--- a/Snowflake.Data/Core/Session/SFSessionHttpClientProperties.cs
+++ b/Snowflake.Data/Core/Session/SFSessionHttpClientProperties.cs
@@ -76,6 +76,7 @@ internal HttpClientConfig BuildHttpClientConfig()
{
return new HttpClientConfig(
!insecureMode,
+ proxyProperties.useProxy,
proxyProperties.proxyHost,
proxyProperties.proxyPort,
proxyProperties.proxyUser,
diff --git a/Snowflake.Data/Core/Session/SFSessionHttpClientProxyProperties.cs b/Snowflake.Data/Core/Session/SFSessionHttpClientProxyProperties.cs
index 4266c585d..5f5ee7a28 100644
--- a/Snowflake.Data/Core/Session/SFSessionHttpClientProxyProperties.cs
+++ b/Snowflake.Data/Core/Session/SFSessionHttpClientProxyProperties.cs
@@ -6,6 +6,7 @@ namespace Snowflake.Data.Core
internal class SFSessionHttpClientProxyProperties
{
+ internal bool useProxy = false;
internal string proxyHost = null;
internal string proxyPort = null;
internal string nonProxyHosts = null;
@@ -22,7 +23,10 @@ internal class Extractor : IExtractor
public SFSessionHttpClientProxyProperties ExtractProperties(SFSessionProperties propertiesDictionary)
{
var properties = new SFSessionHttpClientProxyProperties();
- if (Boolean.Parse(propertiesDictionary[SFSessionProperty.USEPROXY]))
+
+ properties.useProxy = Boolean.Parse(propertiesDictionary[SFSessionProperty.USEPROXY]);
+
+ if (properties.useProxy)
{
// Let's try to get the associated RestRequester
propertiesDictionary.TryGetValue(SFSessionProperty.PROXYHOST, out properties.proxyHost);
diff --git a/Snowflake.Data/Snowflake.Data.csproj b/Snowflake.Data/Snowflake.Data.csproj
index 0621c5fb0..2c37269be 100644
--- a/Snowflake.Data/Snowflake.Data.csproj
+++ b/Snowflake.Data/Snowflake.Data.csproj
@@ -1,4 +1,4 @@
-
+
net6.0;net471;net472
net6.0
@@ -17,7 +17,7 @@
Full
7.3
-
+
@@ -31,7 +31,7 @@
-
+
@@ -45,7 +45,7 @@
-
+
full
True
@@ -55,13 +55,13 @@
full
True
-
+
true
true
$(Version)
-
+