@@ -29,7 +29,7 @@ const (
2929)
3030
3131var (
32- identifierRe = regexp .MustCompile ("[A-Za-z][A-Za-z0-9_]*" )
32+ identifierRe = regexp .MustCompile ("^ [A-Za-z][A-Za-z0-9_]*$ " )
3333)
3434
3535// ParseUriTemplate parses a [RFC 6570] URI template as an `api.PathTemplate`.
@@ -73,25 +73,40 @@ func parseExpression(input string) (*api.PathSegment, int, error) {
7373 return nil , 0 , fmt .Errorf ("missing `{` character in expression %q" , input )
7474 }
7575 tail := input [1 :]
76- if strings .IndexAny (tail , "+#" ) == 0 {
77- return nil , 0 , fmt .Errorf ("level 2 expressions unsupported input=%q" , input )
76+ end := strings .IndexRune (tail , endExpression )
77+ if end == - 1 {
78+ return nil , 0 , fmt .Errorf ("missing `}` character at the end of the expression %q" , input )
79+ }
80+ tail = tail [:end ]
81+ if tail == "" {
82+ return nil , 0 , fmt .Errorf ("empty expression %q" , input )
7883 }
84+
7985 if strings .IndexAny (tail , "./?&" ) == 0 {
8086 return nil , 0 , fmt .Errorf ("level 3 expressions unsupported input=%q" , input )
8187 }
8288 if strings .IndexAny (tail , "=,!@|" ) == 0 {
8389 return nil , 0 , fmt .Errorf ("reserved character on expression %q" , input )
8490 }
85- match := identifierRe .FindStringIndex (tail )
86- if match [0 ] != 0 {
87- return nil , 0 , fmt .Errorf ("no identifier found on expression %q" , input )
91+
92+ allowReserved := false
93+ switch tail [0 ] {
94+ case '+' :
95+ allowReserved = true
96+ tail = tail [1 :]
97+ case '#' :
98+ return nil , 0 , fmt .Errorf ("level 2 fragment expressions unsupported input=%q" , input )
8899 }
89- id := tail [0 :match [1 ]]
90- tail = tail [match [1 ]:]
91- if tail == "" || tail [0 ] != endExpression {
92- return nil , 0 , fmt .Errorf ("missing `}` character at the end of the expression %q" , input )
100+
101+ match := identifierRe .MatchString (tail )
102+ if ! match {
103+ return nil , 0 , fmt .Errorf ("invalid varname found on expression %q" , input )
104+ }
105+ variable := api .NewPathVariable (tail ).WithMatch ()
106+ if allowReserved {
107+ variable .WithAllowReserved ()
93108 }
94- return & api.PathSegment {Variable : api . NewPathVariable ( id ). WithMatch () }, match [ 1 ] + 2 , nil
109+ return & api.PathSegment {Variable : variable }, end + 2 , nil
95110}
96111
97112// parseLiteral() extracts a literal value from `input`.
0 commit comments