Skip to content

Commit e092835

Browse files
SNOW-977565: Added start and end symbol to match full regex to bypass proxy server. (#899)
### Description Added start and end symbol to match string with full regex to bypass proxy server. ### Checklist - [x] Code compiles correctly - [x] Code is formatted according to [Coding Conventions](../CodingConventions.md) - [x] Created tests which fail without the change (if possible) - [x] All tests passing (`dotnet test`) - [x] Extended the README / documentation, if necessary - [x] Provide JIRA issue id (if possible) or GitHub issue id in PR name
1 parent dfba44e commit e092835

File tree

4 files changed

+83
-4
lines changed

4 files changed

+83
-4
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ The following table lists all valid connection properties:
163163
| 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. |
164164
| PROXYUSER | No | The username for authenticating to the proxy server. <br/> <br/> This parameter was introduced in v2.0.4. |
165165
| 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. |
166-
| 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/> <br/> This parameter was introduced in v2.0.4. |
166+
| 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. |
167167
| 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. |
168168
| CLIENT_CONFIG_FILE | No | The location of the client configuration json file. In this file you can configure easy logging feature. |
169169
| 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. |
@@ -377,6 +377,22 @@ using (IDbConnection conn = new SnowflakeDbConnection())
377377
}
378378
```
379379

380+
The NONPROXYHOSTS property could be set to specify if the server proxy should be bypassed by an specified host. This should be defined using the full host url or including the url + `*` wilcard symbol.
381+
382+
Examples:
383+
384+
- `*` (Bypassed all hosts from the proxy server)
385+
- `*.snowflakecomputing.com` ('Bypass all host that ends with `snowflakecomputing.com`')
386+
- `https:\\testaccount.snowflakecomputing.com` (Bypass proxy server using full host url).
387+
- `*.myserver.com | *testaccount*` (You can specify multiple regex for the property divided by `|`)
388+
389+
390+
> Note: The nonproxyhost value should match the full url including the http or https section. The '*' wilcard could be added to bypass the hostname successfully.
391+
392+
- `myaccount.snowflakecomputing.com` (Not bypassed).
393+
- `*myaccount.snowflakecomputing.com` (Bypassed).
394+
395+
380396
## Using Connection Pools
381397

382398
Instead of creating a connection each time your client application needs to access Snowflake, you can define a cache of Snowflake connections that can be reused as needed. Connection pooling usually reduces the lag time to make a connection. However, it can slow down client failover to an alternative DNS when a DNS problem occurs.

Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,60 @@ public void TestInvalidProxySettingFromConnectionString()
15401540
}
15411541
}
15421542

1543+
[Test]
1544+
[TestCase("*")]
1545+
[TestCase("*{0}*")]
1546+
[TestCase("^*{0}*")]
1547+
[TestCase("*{0}*$")]
1548+
[TestCase("^*{0}*$")]
1549+
[TestCase("^nonmatch*{0}$|*")]
1550+
[TestCase("*a*", "a")]
1551+
[TestCase("*la*", "la")]
1552+
public void TestNonProxyHostShouldBypassProxyServer(string regexHost, string proxyHost = "proxyserverhost")
1553+
{
1554+
using (var conn = new SnowflakeDbConnection())
1555+
{
1556+
// Arrange
1557+
var host = ResolveHost();
1558+
var nonProxyHosts = string.Format(regexHost, $"{host}");
1559+
conn.ConnectionString =
1560+
$"{ConnectionString}USEPROXY=true;PROXYHOST={proxyHost};NONPROXYHOSTS={nonProxyHosts};PROXYPORT=3128;";
1561+
1562+
// Act
1563+
conn.Open();
1564+
1565+
// Assert
1566+
// The connection would fail to open if the web proxy would be used because the proxy is configured to a non-existent host.
1567+
Assert.AreEqual(ConnectionState.Open, conn.State);
1568+
}
1569+
}
1570+
1571+
[Test]
1572+
[TestCase("invalid{0}")]
1573+
[TestCase("*invalid{0}*")]
1574+
[TestCase("^invalid{0}$")]
1575+
[TestCase("*a.b")]
1576+
[TestCase("a", "a")]
1577+
[TestCase("la", "la")]
1578+
public void TestNonProxyHostShouldNotBypassProxyServer(string regexHost, string proxyHost = "proxyserverhost")
1579+
{
1580+
using (var conn = new SnowflakeDbConnection())
1581+
{
1582+
// Arrange
1583+
var nonProxyHosts = string.Format(regexHost, $"{testConfig.host}");
1584+
conn.ConnectionString =
1585+
$"{ConnectionString}connection_timeout=5;USEPROXY=true;PROXYHOST={proxyHost};NONPROXYHOSTS={nonProxyHosts};PROXYPORT=3128;";
1586+
1587+
// Act/Assert
1588+
// The connection would fail to open if the web proxy would be used because the proxy is configured to a non-existent host.
1589+
var exception = Assert.Throws<SnowflakeDbException>(() => conn.Open());
1590+
1591+
// Assert
1592+
Assert.AreEqual(270001, exception.ErrorCode);
1593+
AssertIsConnectionFailure(exception);
1594+
}
1595+
}
1596+
15431597
[Test]
15441598
public void TestUseProxyFalseWithInvalidProxyConnectionString()
15451599
{
@@ -1561,7 +1615,7 @@ public void TestInvalidProxySettingWithByPassListFromConnectionString()
15611615
= ConnectionString
15621616
+ String.Format(
15631617
";useProxy=true;proxyHost=Invalid;proxyPort=8080;nonProxyHosts={0}",
1564-
"*.foo.com %7C" + testConfig.account + ".snowflakecomputing.com|" + testConfig.host);
1618+
$"*.foo.com %7C{testConfig.account}.snowflakecomputing.com|*{testConfig.host}*");
15651619
conn.Open();
15661620
// Because testConfig.host is in the bypass list, the proxy should not be used
15671621
}
@@ -2169,6 +2223,7 @@ public void TestNativeOktaSuccess()
21692223
Assert.AreEqual(ConnectionState.Open, conn.State);
21702224
}
21712225
}
2226+
21722227
}
21732228
}
21742229

Snowflake.Data.Tests/SFBaseTest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ public SFBaseTestAsync()
155155
testConfig.password);
156156

157157
protected TestConfig testConfig { get; }
158+
159+
protected string ResolveHost()
160+
{
161+
return testConfig.host ?? $"{testConfig.account}.snowflakecomputing.com";
162+
}
158163
}
159164

160165
[SetUpFixture]

Snowflake.Data/Core/HttpUtil.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
using System.Collections.Specialized;
1313
using System.Web;
1414
using System.Security.Authentication;
15-
using System.Runtime.InteropServices;
1615
using System.Linq;
1716
using Snowflake.Data.Core.Authenticator;
1817

@@ -186,7 +185,11 @@ internal HttpMessageHandler SetupCustomHttpHandler(HttpClientConfig config)
186185
entry = entry.Replace(".", "[.]");
187186
// * -> .* because * is a quantifier and need a char or group to apply to
188187
entry = entry.Replace("*", ".*");
189-
188+
189+
entry = entry.StartsWith("^") ? entry : $"^{entry}";
190+
191+
entry = entry.EndsWith("$") ? entry : $"{entry}$";
192+
190193
// Replace with the valid entry syntax
191194
bypassList[i] = entry;
192195

0 commit comments

Comments
 (0)