Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-1333163 support for default proxy #997

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion Snowflake.Data.Tests/SFBaseTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) 2012-2021 Snowflake Computing Inc. All rights reserved.
*/

81 changes: 66 additions & 15 deletions Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs
Original file line number Diff line number Diff line change
@@ -3,16 +3,15 @@
*/

using System.Net.Http;
using NUnit.Framework;
using Snowflake.Data.Core;
using RichardSzalay.MockHttp;
using System.Threading.Tasks;
using System.Net;
using System;

namespace Snowflake.Data.Tests.UnitTests
{
using NUnit.Framework;
using Snowflake.Data.Core;
using RichardSzalay.MockHttp;
using System.Threading.Tasks;
using System.Net;
using System;

[TestFixture]
class HttpUtilTest
{
@@ -102,48 +101,100 @@ public void TestGetJitter(int seconds)
}

[Test]
public void ShouldCreateHttpClientHandlerWithProxy()
public void TestCreateHttpClientHandlerWithExplicitProxy()
{
// 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 TestCreateHttpClientHandlerWithDefaultProxy()
{
// given
var config = new HttpClientConfig(
true,
true,
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 TestCreateHttpClientHandlerWithoutProxy()
{
// given
var config = new HttpClientConfig(
false,
false,
null,
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);
}

[Test]
public void TestIgnoreProxyDetailsIfProxyDisabled()
{
// given
var config = new HttpClientConfig(
true,
false,
"snowflake.com",
"123",
"testUser",
"proxyPassword",
"localhost",
false,
false,
7
);

// when
var handler = (HttpClientHandler) HttpUtil.Instance.SetupCustomHttpHandler(config);

// then
Assert.IsFalse(handler.UseProxy);
Assert.IsNull(handler.Proxy);
53 changes: 53 additions & 0 deletions Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
using Snowflake.Data.Client;
using Snowflake.Data.Core.Authenticator;
using Snowflake.Data.Core.Tools;
using Snowflake.Data.Tests.Util;

namespace Snowflake.Data.Tests.UnitTests
{
@@ -166,6 +167,58 @@ public void TestResolveConnectionArea(string host, string expectedMessage)
Assert.AreEqual(expectedMessage, message);
}

[Test]
public void TestFailWhenProxyConfiguredWithoutPort()
{
// arrange
var connectionString = "ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;proxyHost=localhost";

// act
var thrown = Assert.Throws<SnowflakeDbException>(() => SFSessionProperties.ParseConnectionString(connectionString, null));

// assert
SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.MISSING_CONNECTION_PROPERTY);
Assert.That(thrown.Message, Does.Contain("Required property PROXYPORT is not provided"));
}

[Test]
public void TestFailWhenProxyUserProvidedWithoutProxyPassword()
{
// arrange
var connectionString = "ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;proxyHost=localhost;proxyPort=1234;proxyUser=testUser";

// act
var thrown = Assert.Throws<SnowflakeDbException>(() => SFSessionProperties.ParseConnectionString(connectionString, null));

// assert
SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.MISSING_CONNECTION_PROPERTY);
Assert.That(thrown.Message, Does.Contain("Required property PROXYPASSWORD is not provided"));
}

[Test]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;proxyPort=1234;proxyPassword=xyz", SFSessionProperty.PROXYPORT)]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;proxyUser=testUser;proxyPassword=xyz", SFSessionProperty.PROXYUSER)]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;proxyPassword=xyz", SFSessionProperty.PROXYPASSWORD)]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;useProxy=true;nonProxyHosts=xyz", SFSessionProperty.NONPROXYHOSTS)]
public void TestFailWhenConfiguringProxyDetailsWithoutProxyHost(string connectionString, SFSessionProperty unwantedProperty)
{
// act
var thrown = Assert.Throws<SnowflakeDbException>(() => SFSessionProperties.ParseConnectionString(connectionString, null));

// assert
SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.INVALID_CONNECTION_STRING);
Assert.That(thrown.Message, Does.Contain($"Proxy property {unwantedProperty.ToString()} provided while PROXYHOST is missing"));
}

[Test]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;proxyHost=localhost")]
[TestCase("ACCOUNT=account;USER=test;PASSWORD=test;useProxy=false;proxyHost=localhost;proxyPort=1234;proxyUser=testUser")]
public void TestProxyValidationsOnlyWhenProxyEnabledAndProxyHostConfigured(string connectionString)
{
// act
Assert.DoesNotThrow(() => SFSessionProperties.ParseConnectionString(connectionString, null));
}

public static IEnumerable<TestCase> ConnectionStringTestCases()
{
string defAccount = "testaccount";
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ namespace Snowflake.Data.Tests.UnitTests.Session
public class SFHttpClientProxyPropertiesTest
{
[Test, TestCaseSource(nameof(ProxyPropertiesProvider))]
public void ShouldExtractProxyProperties(ProxyPropertiesTestCase testCase)
public void TestExtractProxyProperties(ProxyPropertiesTestCase testCase)
{
// given
var extractor = new SFSessionHttpClientProxyProperties.Extractor();
@@ -23,6 +23,7 @@ public void ShouldExtractProxyProperties(ProxyPropertiesTestCase testCase)
var proxyProperties = extractor.ExtractProperties(properties);

// then
Assert.AreEqual(testCase.expectedProperties.useProxy, proxyProperties.useProxy);
Assert.AreEqual(testCase.expectedProperties.proxyHost, proxyProperties.proxyHost);
Assert.AreEqual(testCase.expectedProperties.proxyPort, proxyProperties.proxyPort);
Assert.AreEqual(testCase.expectedProperties.nonProxyHosts, proxyProperties.nonProxyHosts);
@@ -37,6 +38,7 @@ public static IEnumerable<ProxyPropertiesTestCase> ProxyPropertiesProvider()
conectionString = "account=test;user=test;password=test",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = false,
proxyHost = null,
proxyPort = null,
nonProxyHosts = null,
@@ -49,6 +51,20 @@ public static IEnumerable<ProxyPropertiesTestCase> ProxyPropertiesProvider()
conectionString = "account=test;user=test;password=test;useProxy=false;proxyHost=snowflake.com;proxyPort=123;nonProxyHosts=localhost;proxyPassword=proxyPassword;proxyUser=Chris",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = false,
proxyHost = null,
proxyPort = null,
nonProxyHosts = null,
proxyPassword = null,
proxyUser = null
}
};
var proxyPropertiesConfiguredButDisabledCase2 = new ProxyPropertiesTestCase()
{
conectionString = "account=test;user=test;password=test;proxyHost=snowflake.com;proxyPort=123;nonProxyHosts=localhost;proxyPassword=proxyPassword;proxyUser=Chris",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = false,
proxyHost = null,
proxyPort = null,
nonProxyHosts = null,
@@ -58,11 +74,12 @@ public static IEnumerable<ProxyPropertiesTestCase> ProxyPropertiesProvider()
};
var proxyPropertiesConfiguredAndEnabledCase = new ProxyPropertiesTestCase()
{
conectionString = "account=test;user=test;password=test;useProxy=true;proxyHost=snowflake.com",
conectionString = "account=test;user=test;password=test;useProxy=true;proxyHost=snowflake.com;proxyPort=1234",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = true,
proxyHost = "snowflake.com",
proxyPort = null,
proxyPort = "1234",
nonProxyHosts = null,
proxyPassword = null,
proxyUser = null
@@ -74,19 +91,35 @@ public static IEnumerable<ProxyPropertiesTestCase> ProxyPropertiesProvider()
"account=test;user=test;password=test;useProxy=true;proxyHost=snowflake.com;proxyPort=123;nonProxyHosts=localhost;proxyPassword=proxyPassword;proxyUser=Chris",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = true,
proxyHost = "snowflake.com",
proxyPort = "123",
nonProxyHosts = "localhost",
proxyPassword = "proxyPassword",
proxyUser = "Chris"
}
};
var defaultProxyEnabled = new ProxyPropertiesTestCase()
{
conectionString = "account=test;user=test;password=test;useProxy=true;",
expectedProperties = new SFSessionHttpClientProxyProperties()
{
useProxy = true,
proxyHost = null,
proxyPort = null,
nonProxyHosts = null,
proxyPassword = null,
proxyUser = null
}
};
return new []
{
noProxyPropertiesCase,
proxyPropertiesConfiguredButDisabledCase,
proxyPropertiesConfiguredButDisabledCase2,
proxyPropertiesConfiguredAndEnabledCase,
proxyPropertiesAllConfiguredAndEnabled
proxyPropertiesAllConfiguredAndEnabled,
defaultProxyEnabled
};
}

107 changes: 59 additions & 48 deletions Snowflake.Data/Core/HttpUtil.cs
Original file line number Diff line number Diff line change
@@ -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,58 +154,66 @@ 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)
httpHandler.UseProxy = config.UseProxy;

if (config.UseProxy && !string.IsNullOrEmpty(config.ProxyHost))
{
logger.Info("Configuring proxy based on connection properties");
var proxy = ConfigureWebProxy(config);
httpHandler.Proxy = proxy;
}
else if (config.UseProxy)
{
// Proxy needed
WebProxy proxy = new WebProxy(config.ProxyHost, int.Parse(config.ProxyPort));
logger.Info("Using a default proxy");
}

// Add credential if provided
if (!String.IsNullOrEmpty(config.ProxyUser))
{
ICredentials credentials = new NetworkCredential(config.ProxyUser, config.ProxyPassword);
proxy.Credentials = credentials;
}
return httpHandler;
}

private WebProxy ConfigureWebProxy(HttpClientConfig config)
{
WebProxy proxy = new WebProxy(config.ProxyHost, int.Parse(config.ProxyPort));

// 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))
// 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++)
{
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;
// 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("*", ".*");

}
proxy.BypassList = bypassList;
}
entry = entry.StartsWith("^") ? entry : $"^{entry}";

HttpClientHandler httpHandlerWithProxy = (HttpClientHandler)httpHandler;
httpHandlerWithProxy.UseProxy = true;
httpHandlerWithProxy.Proxy = proxy;
return httpHandlerWithProxy;
entry = entry.EndsWith("$") ? entry : $"{entry}$";

// Replace with the valid entry syntax
bypassList[i] = entry;

}
proxy.BypassList = bypassList;
}
return httpHandler;

return proxy;
}

/// <summary>
@@ -384,7 +395,7 @@ protected override async Task<HttpResponseMessage> 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);
Original file line number Diff line number Diff line change
@@ -179,6 +179,7 @@ public HttpClientConfig BuildHttpClientConfig()
{
return new HttpClientConfig(
!insecureMode,
proxyProperties.useProxy,
proxyProperties.proxyHost,
proxyProperties.proxyPort,
proxyProperties.proxyUser,
Original file line number Diff line number Diff line change
@@ -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);
@@ -34,7 +38,7 @@ public SFSessionHttpClientProxyProperties ExtractProperties(SFSessionProperties
if (!String.IsNullOrEmpty(properties.nonProxyHosts))
{
// The list is url-encoded
// Host names are separated with a URL-escaped pipe symbol (%7C).
// Host names are separated with a URL-escaped pipe symbol (%7C).
properties.nonProxyHosts = HttpUtility.UrlDecode(properties.nonProxyHosts);
}
}
86 changes: 55 additions & 31 deletions Snowflake.Data/Core/Session/SFSessionProperty.cs
Original file line number Diff line number Diff line change
@@ -220,37 +220,7 @@
}

UpdatePropertiesForSpecialCases(properties, connectionString);

var useProxy = false;
if (properties.ContainsKey(SFSessionProperty.USEPROXY))
{
try
{
useProxy = Boolean.Parse(properties[SFSessionProperty.USEPROXY]);
}
catch (Exception e)
{
// The useProxy setting is not a valid boolean value
logger.Error("Unable to connect", e);
throw new SnowflakeDbException(e,
SFError.INVALID_CONNECTION_STRING,
e.Message);
}
}

// Based on which proxy settings have been provided, update the required settings list
if (useProxy)
{
// If useProxy is true, then proxyhost and proxy port are mandatory
SFSessionProperty.PROXYHOST.GetAttribute<SFSessionPropertyAttr>().required = true;
SFSessionProperty.PROXYPORT.GetAttribute<SFSessionPropertyAttr>().required = true;

// If a username is provided, then a password is required
if (properties.ContainsKey(SFSessionProperty.PROXYUSER))
{
SFSessionProperty.PROXYPASSWORD.GetAttribute<SFSessionPropertyAttr>().required = true;
}
}
ValidateProxy(properties);

if (password != null && password.Length > 0)
{
@@ -296,6 +266,60 @@
? "Connecting to CHINA Snowflake domain"
: "Connecting to GLOBAL Snowflake domain";


private static void ValidateProxy(SFSessionProperties properties)
{
var useProxy = false;
if (properties.ContainsKey(SFSessionProperty.USEPROXY))
{
try
{
useProxy = Boolean.Parse(properties[SFSessionProperty.USEPROXY]);
}
catch (Exception e)
{

Check warning on line 280 in Snowflake.Data/Core/Session/SFSessionProperty.cs

Codecov / codecov/patch

Snowflake.Data/Core/Session/SFSessionProperty.cs#L279-L280

Added lines #L279 - L280 were not covered by tests
// The useProxy setting is not a valid boolean value
logger.Error("Unable to connect", e);
throw new SnowflakeDbException(e,
SFError.INVALID_CONNECTION_STRING,
e.Message);

Check warning on line 285 in Snowflake.Data/Core/Session/SFSessionProperty.cs

Codecov / codecov/patch

Snowflake.Data/Core/Session/SFSessionProperty.cs#L282-L285

Added lines #L282 - L285 were not covered by tests
}
}

var isProxyHostProvided = properties.IsNonEmptyValueProvided(SFSessionProperty.PROXYHOST);
if (useProxy && isProxyHostProvided)
{
if (!properties.IsNonEmptyValueProvided(SFSessionProperty.PROXYPORT))
{
throw new SnowflakeDbException(SFError.MISSING_CONNECTION_PROPERTY, SFSessionProperty.PROXYPORT.ToString());
}
if (properties.IsNonEmptyValueProvided(SFSessionProperty.PROXYUSER) &&
!properties.IsNonEmptyValueProvided(SFSessionProperty.PROXYPASSWORD))
{
throw new SnowflakeDbException(SFError.MISSING_CONNECTION_PROPERTY, SFSessionProperty.PROXYPASSWORD.ToString());
}
}

if (useProxy && !isProxyHostProvided)
{
var property = FindProxyDetailOtherThanHost(properties);
if (property != null)
{
var exception = new Exception($"Proxy property {property.ToString()} provided while {SFSessionProperty.PROXYHOST.ToString()} is missing");
logger.Error("Unable to connect", exception);
throw new SnowflakeDbException(exception, SFError.INVALID_CONNECTION_STRING, exception.Message);
}
}
}

private static SFSessionProperty? FindProxyDetailOtherThanHost(SFSessionProperties properties)
{
var proxyProperties = new[] { SFSessionProperty.PROXYPORT, SFSessionProperty.PROXYUSER, SFSessionProperty.PROXYPASSWORD, SFSessionProperty.NONPROXYHOSTS }
.Where(properties.IsNonEmptyValueProvided)
.ToArray();
return proxyProperties.Length == 0 ? (SFSessionProperty?) null : proxyProperties[0];
}

private static void ValidateAuthenticator(SFSessionProperties properties)
{
var knownAuthenticators = new[] {
10 changes: 5 additions & 5 deletions doc/Connecting.md
Original file line number Diff line number Diff line change
@@ -34,11 +34,11 @@ 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. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYHOST | Depends | The hostname of the proxy server. <br/> <br/> If USEPROXY is set to `true`, you must set this parameter. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYPORT | Depends | The port number of the proxy server. <br/> <br/> If USEPROXY is set to `true`, you must set this parameter. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYUSER | No | The username for authenticating to the proxy server. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYPASSWORD | Depends | The password for authenticating to the proxy server. <br/> <br/> If USEPROXY is `true` and PROXYUSER is set, you must set this parameter. <br/> <br/> 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. <br/> The host target value should fully match with any item from the proxy host list to bypass the proxy server. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYHOST | Depends | The hostname of the proxy server. <br/> <br/> Proxy parameters are used only if you enable the proxy by setting USEPROXY to `true`. It is required if you provide your own proxy configuration. Do not provide this value if you want to use a default proxy. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYPORT | Depends | The port number of the proxy server. <br/> <br/> If USEPROXY is set to `true` and PROXYHOST is provided, you must set this parameter. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYUSER | No | The username for authenticating to the proxy server. Parameter is used only if USEPROXY is set to `true` and PROXYHOST is provided. <br/> <br/> This parameter was introduced in v2.0.4. |
| PROXYPASSWORD | Depends | The password for authenticating to the proxy server. Parameter is used only if USEPROXY is set to `true` and PROXYHOST is provided. <br/> <br/> If USEPROXY is `true` and PROXYHOST and PROXYUSER are set, you must set this parameter. <br/> <br/> 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. <br /> The parameter is used only if USEPROXY is set to `true` and PROXYHOST is provided. <br /> Separate the hostnames with a pipe symbol (\|). You can also use an asterisk (`*`) as a wildcard. <br/> The host target value should fully match with any item from the proxy host list to bypass the proxy server. <br/> <br/> This parameter was introduced in v2.0.4. |
| FILE_TRANSFER_MEMORY_THRESHOLD | No | The maximum number of bytes to store in memory used in order to provide a file encryption. If encrypting/decrypting file size exceeds provided value a temporary file will be created and the work will be continued in the temporary file instead of memory. <br/> If no value provided 1MB will be used as a default value (that is 1048576 bytes). <br/> It is possible to configure any integer value bigger than zero representing maximal number of bytes to reside in memory. |
| CLIENT_CONFIG_FILE | No | The location of the client configuration json file. In this file you can configure easy logging feature. |
| ALLOWUNDERSCORESINHOST | No | Specifies whether to allow underscores in account names. This impacts PrivateLink customers whose account names contain underscores. In this situation, you must override the default value by setting allowUnderscoresInHost to true. |
Loading