Repository: snowflakedb/gosnowflake
Pull request #757 (2023-03-17 00:30:56)

SNOW-761744 Added URL Validator and URL Encoder
### Description
Added URL Validator to ensure that the SSO URL being used in external browser is valid. Also added URL Encoder to encode base64 strings to url safe format. 

### Checklist
- [ ] Code compiles correctly
- [ ] Run ``make fmt`` to fix inconsistent formats
- [ ] Run ``make lint`` to get lint errors and fix all of them
- [ ] Created tests which fail without the change (if possible)
- [ ] All tests passing
- [ ] Extended the README / documentation, if necessary


github-actions[bot]: **CLA Assistant Lite bot:** <br/>Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our [Contributor License Agreement](https://github.com/Snowflake-Labs/CLA/blob/main/README.md) before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.<br/>
   - - -
   I have read the CLA Document and I hereby sign the CLA
   - - -
   **Harsh Chaturvedi** seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please [add the email address used for this commit to your account](https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/#commits-are-not-linked-to-any-user).<br/><sub>You can retrigger this bot by commenting **recheck** in this Pull Request</sub>
sfc-gh-hchaturvedi: I have read the CLA Document and I hereby sign the CLA
sfc-gh-wshangguan: So we just add some util functions without using them at this moment?

Patch:
diff --git a/url_util.go b/url_util.go
new file mode 100644
index 0000000..c6a9364
--- /dev/null
+++ b/url_util.go
@@ -0,0 +1,29 @@
+package gosnowflake
+
+import (
+	"net/url"
+	"regexp"
+)
+
+var (
+	matcher, _ = regexp.Compile(`^http(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z@:])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\&\(\)\/\\\+&%\$#_=@]*)?$`)
+)
+
+func isValidURL(targetURL string) bool {
+	if !matcher.MatchString(targetURL) {
+		logger.Infof(" The provided URL is not a valid URL - " + targetURL)
+		return false
+	}
+	return true
+}
+
+func urlEncode(targetString string) string {
+	// We use QueryEscape instead of PathEscape here
+	// for consistency across Drivers. For example:
+	// QueryEscape escapes space as "+" whereas PE
+	// it as %20F. PE also does not escape @ or &
+	// either but QE does.
+	// The behavior of QE in Golang is more in sync
+	// with URL encoders in Python and Java hence the choice
+	return url.QueryEscape(targetString)
+}


Test patch:
diff --git a/util_test.go b/util_test.go
index b0a5f3c..9778d18 100644
--- a/util_test.go
+++ b/util_test.go
@@ -230,3 +230,44 @@ func TestGetMin(t *testing.T) {
 		}
 	}
 }
+
+type tcURLList struct {
+	in  string
+	out bool
+}
+
+func TestValidURL(t *testing.T) {
+	testcases := []tcURLList{
+		{"https://ssoTestURL.okta.com", true},
+		{"https://ssoTestURL.okta.com:8080", true},
+		{"https://ssoTestURL.okta.com/testpathvalue", true},
+		{"-a calculator", false},
+		{"This is a random test", false},
+		{"file://TestForFile", false},
+	}
+	for _, test := range testcases {
+		result := isValidURL(test.in)
+		if test.out != result {
+			t.Errorf("Failed to validate URL, input :%v, expected: %v, got: %v", test.in, test.out, result)
+		}
+	}
+}
+
+type tcEncodeList struct {
+	in  string
+	out string
+}
+
+func TestEncodeURL(t *testing.T) {
+	testcases := []tcEncodeList{
+		{"Hello @World", "Hello+%40World"},
+		{"Test//String", "Test%2F%2FString"},
+	}
+
+	for _, test := range testcases {
+		result := urlEncode(test.in)
+		if test.out != result {
+			t.Errorf("Failed to encode string, input %v, expected: %v, got: %v", test.in, test.out, result)
+		}
+	}
+}