-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy pathcommon.go
145 lines (134 loc) · 3.31 KB
/
common.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package yarx
import (
"errors"
"fmt"
"net/url"
"regexp"
"sort"
"strings"
)
var (
ErrReverseNotSupported = errors.New("reverse type is not supported yet")
ErrRequestNotSupported = errors.New("request variable is not supported yet")
)
var variableRegex = regexp.MustCompile(`{{([a-zA-Z0-9_]+)}}`)
func variableToRegexp(template string, varContext map[string]interface{}, withRapper bool, fixNewline bool) (*regexp.Regexp, string, error) {
var replacedStr string
if !strings.Contains(template, "{{") {
replacedStr = template
template = regexp.QuoteMeta(template)
if withRapper {
template = "^" + template + "$"
}
} else {
replaceMap := make(map[string]string)
for i, arr := range variableRegex.FindAllStringSubmatch(template, -1) {
if val, ok := varContext[arr[1]]; ok {
switch v := val.(type) {
case []byte, byte:
template = strings.ReplaceAll(template, arr[0], fmt.Sprintf("%s", v))
default:
template = strings.ReplaceAll(template, arr[0], fmt.Sprintf("%v", v))
}
} else {
namedGroup := fmt.Sprintf(`(?P<%s>\w+)`, arr[1])
// 这里不能直接替换,因为数据中的 ? . () 之类的不应该被视为正则, 这里用占位符先弄一下,后面转义后再替换
// 这个占位符既不能是正则中的字符,也不能是 url 需要转移的字符
placeholder := fmt.Sprintf(`---variable-%d---`, i)
replaceMap[placeholder] = namedGroup
template = strings.Replace(template, arr[0], placeholder, 1)
}
}
replacedStr = template
template = regexp.QuoteMeta(template)
for k, v := range replaceMap {
template = strings.Replace(template, k, v, 1)
}
}
if withRapper {
template = "^" + template + "$"
}
if fixNewline {
template = strings.Replace(template, "\n", ".{1,2}?", -1)
}
template = "(?s)" + template
re, err := regexp.Compile(template)
return re, replacedStr, err
}
func SortedURI(u *url.URL) string {
result := u.Opaque
if result == "" {
result = u.EscapedPath()
if result == "" {
result = "/"
}
} else {
if strings.HasPrefix(result, "//") {
result = u.Scheme + ":" + result
}
}
p, err := url.PathUnescape(result)
if err == nil {
result = p
}
query := SortedQuery(u.RawQuery)
if query != "" {
result = result + "?" + query
}
return result
}
func SortedQueryKey(query string) string {
var queryKeys []string
for query != "" {
key := query
if i := strings.IndexAny(key, "&"); i >= 0 {
key, query = key[:i], key[i+1:]
} else {
query = ""
}
if key == "" {
continue
}
if i := strings.Index(key, "="); i >= 0 {
key = key[:i]
} else {
continue
}
queryKeys = append(queryKeys, key)
}
sort.Strings(queryKeys)
return strings.Join(queryKeys, "#")
}
func SortedQuery(query string) string {
var m = make(map[string]string)
var keys []string
for query != "" {
key := query
if i := strings.IndexAny(key, "&"); i >= 0 {
key, query = key[:i], key[i+1:]
} else {
query = ""
}
if key == "" {
continue
}
value := ""
if i := strings.Index(key, "="); i >= 0 {
key, value = key[:i], key[i+1:]
}
m[key] = value
keys = append(keys, key)
}
sort.Strings(keys)
var buf strings.Builder
for _, key := range keys {
value := m[key]
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(key)
buf.WriteByte('=')
buf.WriteString(value)
}
return buf.String()
}