...
1 package restful
2
3
4
5
6
7 import (
8 "bytes"
9 "fmt"
10 "regexp"
11 "strings"
12 )
13
14
15
16 type pathExpression struct {
17 LiteralCount int
18 VarNames []string
19 VarCount int
20 Matcher *regexp.Regexp
21 Source string
22 tokens []string
23 }
24
25
26
27 func newPathExpression(path string) (*pathExpression, error) {
28 expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path)
29 compiled, err := regexp.Compile(expression)
30 if err != nil {
31 return nil, err
32 }
33 return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil
34 }
35
36
37 func templateToRegularExpression(template string) (expression string, literalCount int, varNames []string, varCount int, tokens []string) {
38 var buffer bytes.Buffer
39 buffer.WriteString("^")
40
41 tokens = tokenizePath(template)
42 for _, each := range tokens {
43 if each == "" {
44 continue
45 }
46 buffer.WriteString("/")
47 if strings.HasPrefix(each, "{") {
48
49 colon := strings.Index(each, ":")
50 var varName string
51 if colon != -1 {
52
53 varName = strings.TrimSpace(each[1:colon])
54 paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1])
55 if paramExpr == "*" {
56 buffer.WriteString("(.*)")
57 } else {
58 buffer.WriteString(fmt.Sprintf("(%s)", paramExpr))
59 }
60 } else {
61
62 varName = strings.TrimSpace(each[1 : len(each)-1])
63 buffer.WriteString("([^/]+?)")
64 }
65 varNames = append(varNames, varName)
66 varCount += 1
67 } else {
68 literalCount += len(each)
69 encoded := each
70 buffer.WriteString(regexp.QuoteMeta(encoded))
71 }
72 }
73 return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens
74 }
75
View as plain text