|
|
|
@ -73,14 +73,17 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash |
|
|
|
tpl[idxs[i]:end]) |
|
|
|
} |
|
|
|
// Build the regexp pattern.
|
|
|
|
varIdx := i / 2 |
|
|
|
fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(varIdx), patt) |
|
|
|
if patt[0] == '(' && patt[len(patt)-1] == ')' { |
|
|
|
fmt.Fprintf(pattern, "%s%s", regexp.QuoteMeta(raw), patt) |
|
|
|
} else { |
|
|
|
fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) |
|
|
|
} |
|
|
|
// Build the reverse template.
|
|
|
|
fmt.Fprintf(reverse, "%s%%s", raw) |
|
|
|
|
|
|
|
// Append variable name and compiled pattern.
|
|
|
|
varsN[varIdx] = name |
|
|
|
varsR[varIdx], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) |
|
|
|
varsN[i/2] = name |
|
|
|
varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
@ -246,30 +249,17 @@ type routeRegexpGroup struct { |
|
|
|
func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { |
|
|
|
// Store host variables.
|
|
|
|
if v.host != nil { |
|
|
|
hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) |
|
|
|
if hostVars != nil { |
|
|
|
subexpNames := v.host.regexp.SubexpNames() |
|
|
|
varName := 0 |
|
|
|
for i, name := range subexpNames[1:] { |
|
|
|
if name != "" && name == varGroupName(varName) { |
|
|
|
m.Vars[v.host.varsN[varName]] = hostVars[i+1] |
|
|
|
varName++ |
|
|
|
} |
|
|
|
} |
|
|
|
host := getHost(req) |
|
|
|
matches := v.host.regexp.FindStringSubmatchIndex(host) |
|
|
|
if len(matches) > 0 { |
|
|
|
extractVars(host, matches, v.host.varsN, m.Vars) |
|
|
|
} |
|
|
|
} |
|
|
|
// Store path variables.
|
|
|
|
if v.path != nil { |
|
|
|
pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) |
|
|
|
if pathVars != nil { |
|
|
|
subexpNames := v.path.regexp.SubexpNames() |
|
|
|
varName := 0 |
|
|
|
for i, name := range subexpNames[1:] { |
|
|
|
if name != "" && name == varGroupName(varName) { |
|
|
|
m.Vars[v.path.varsN[varName]] = pathVars[i+1] |
|
|
|
varName++ |
|
|
|
} |
|
|
|
} |
|
|
|
matches := v.path.regexp.FindStringSubmatchIndex(req.URL.Path) |
|
|
|
if len(matches) > 0 { |
|
|
|
extractVars(req.URL.Path, matches, v.path.varsN, m.Vars) |
|
|
|
// Check if we should redirect.
|
|
|
|
if v.path.strictSlash { |
|
|
|
p1 := strings.HasSuffix(req.URL.Path, "/") |
|
|
|
@ -288,16 +278,10 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) |
|
|
|
} |
|
|
|
// Store query string variables.
|
|
|
|
for _, q := range v.queries { |
|
|
|
queryVars := q.regexp.FindStringSubmatch(q.getUrlQuery(req)) |
|
|
|
if queryVars != nil { |
|
|
|
subexpNames := q.regexp.SubexpNames() |
|
|
|
varName := 0 |
|
|
|
for i, name := range subexpNames[1:] { |
|
|
|
if name != "" && name == varGroupName(varName) { |
|
|
|
m.Vars[q.varsN[varName]] = queryVars[i+1] |
|
|
|
varName++ |
|
|
|
} |
|
|
|
} |
|
|
|
queryUrl := q.getUrlQuery(req) |
|
|
|
matches := q.regexp.FindStringSubmatchIndex(queryUrl) |
|
|
|
if len(matches) > 0 { |
|
|
|
extractVars(queryUrl, matches, q.varsN, m.Vars) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -315,3 +299,16 @@ func getHost(r *http.Request) string { |
|
|
|
return host |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func extractVars(input string, matches []int, names []string, output map[string]string) { |
|
|
|
matchesCount := 0 |
|
|
|
prevEnd := -1 |
|
|
|
for i := 2; i < len(matches) && matchesCount < len(names); i += 2 { |
|
|
|
if prevEnd < matches[i+1] { |
|
|
|
value := input[matches[i]:matches[i+1]] |
|
|
|
output[names[matchesCount]] = value |
|
|
|
prevEnd = matches[i+1] |
|
|
|
matchesCount++ |
|
|
|
} |
|
|
|
} |
|
|
|
} |