Repository: txtdirect/txtdirect (go)

Issue:
[placeholders]: Default placeholders shouldn't overwrite custom placeholders
**Is this a BUG REPORT or FEATURE REQUEST?**:
bug

**What happened**:
Currently, the default placeholders would overwrite the named regex placeholders in case of a name collision.

**What you expected to happen**:
Use a new prefix for custom placeholders like named regex placeholders to avoid overwriting them.

**How to reproduce it (as minimally and precisely as possible)**:
Using the same names as default placeholders for named regex placeholder. like "host" and etc.

**Anything else we need to know?**:
What is the best prefix to use? suggestions:
- `{_my-named-regex}` "_"
- `{RE_my-named-regex}` "RE_"
- `{$my-named-regex}` "$"

**Environment**:
- TXTDirect version:  `master`


Pull request:
[placeholders]: Add "$" prefix for named regex placeholders
**What this PR does / why we need it**:
Adds "$" prefix for named regex placeholders

**Which issue this PR fixes**:
fixes #333 

**Special notes for your reviewer**:

**Release note**:
<!--
Optional one line note for this specific change, that can be used in a release-note or changelog.
-->
```release-note

```


Patch:
diff --git a/placeholders.go b/placeholders.go
index e69bdab..0ab58a3 100644
--- a/placeholders.go
+++ b/placeholders.go
@@ -25,7 +25,7 @@ import (
 )
 
 // PlaceholderRegex finds the placeholders like {x}
-var PlaceholderRegex = regexp.MustCompile("{[~>?]?\\w+}")
+var PlaceholderRegex = regexp.MustCompile("{[~>?$]?\\w+}")
 
 // parsePlaceholders gets a string input and looks for placeholders inside
 // the string. it will then replace them with the actual data from the request
@@ -128,13 +128,13 @@ func parsePlaceholders(input string, r *http.Request, pathSlice []string) (strin
 		}
 
 		// Named regex matches
-		if regexp.MustCompile("([a-zA-Z]+[0-9]*)").MatchString(string(placeholder[0][1 : len(placeholder[0])-1])) {
+		if regexp.MustCompile("(\\$[a-zA-Z]+[0-9]*)").MatchString(string(placeholder[0][1 : len(placeholder[0])-1])) {
 			matches := r.Context().Value("regexMatches")
 			mapReflect := reflect.ValueOf(matches)
 			if mapReflect.Kind() == reflect.Map {
 				iterator := reflect.ValueOf(matches).MapRange()
 				for iterator.Next() {
-					if iterator.Key().String() == string(placeholder[0][1:len(placeholder[0])-1]) {
+					if iterator.Key().String() == string(placeholder[0][2:len(placeholder[0])-1]) {
 						input = strings.Replace(input, placeholder[0], iterator.Value().String(), -1)
 					}
 				}


Test patch:
diff --git a/e2e/gometa/zonefile b/e2e/gometa/zonefile
index 109e56f..85fe101 100644
--- a/e2e/gometa/zonefile
+++ b/e2e/gometa/zonefile
@@ -28,4 +28,4 @@ _redirect.empty-to.gometa.path.example.com.                IN TXT "v=txtv0;to=wr
 
 custom-regex.gometa.path.example.com.                      IN A   172.20.10.2
 _redirect.custom-regex.gometa.path.example.com.            IN TXT "v=txtv0;type=path;root=https://no-path.gometa.path.example.com{uri};re=^/(?P<repo>[^/]*)(?P<subpath>/.*)?$"
-_redirect._._.custom-regex.gometa.path.example.com.        IN TXT "v=txtv0;type=gometa;to=https://package.gometa.path.example.com/{repo}"
+_redirect._._.custom-regex.gometa.path.example.com.        IN TXT "v=txtv0;type=gometa;to=https://package.gometa.path.example.com/{$repo}"
diff --git a/path_test.go b/path_test.go
index 9dbaf3e..5c7d6a1 100644
--- a/path_test.go
+++ b/path_test.go
@@ -207,21 +207,21 @@ func Test_zoneFromPathRegexPlaceholders(t *testing.T) {
 		},
 		{
 			"https://example.com/12345-some-path?query=string&more=stuff",
-			"https://example.com/{a}/{b}",
+			"https://example.com/{$a}/{$b}",
 			"",
 			"\\?query=(?P<a>[^&]+)\\&more=(?P<b>[^&]+)",
 			"https://example.com/string/stuff",
 		},
 		{
 			"https://example.com/12345-some-path?query=string&more=stuff&test=testing",
-			"https://example.com/{a}/{b}/{c}",
+			"https://example.com/{$a}/{$b}/{$c}",
 			"",
 			"\\?query=(?P<b>[^&]+)\\&more=(?P<a>[^&]+)\\&test=(?P<c>[^&]+)",
 			"https://example.com/stuff/string/testing",
 		},
 		{
 			"https://example.com/12345-some-path?query=string&more=stuff&test=testing",
-			"https://example.com/{a}/{b2}/{b1}",
+			"https://example.com/{$a}/{$b2}/{$b1}",
 			"",
 			"\\?query=(?P<a>[^&]+)\\&more=(?P<b2>[^&]+)\\&test=(?P<b1>[^&]+)",
 			"https://example.com/string/stuff/testing",