Commit 3e2b1d14 authored by lbogdan's avatar lbogdan Committed by Matt Holt

rewrite: treat "if a not_op b" uniformly by negating "op". (#1696)

parent f4b6f15e
...@@ -45,16 +45,12 @@ func SetupIfMatcher(controller *caddy.Controller) (RequestMatcher, error) { ...@@ -45,16 +45,12 @@ func SetupIfMatcher(controller *caddy.Controller) (RequestMatcher, error) {
// operators // operators
const ( const (
isOp = "is" isOp = "is"
notOp = "not" notOp = "not"
hasOp = "has" hasOp = "has"
notHasOp = "not_has" startsWithOp = "starts_with"
startsWithOp = "starts_with" endsWithOp = "ends_with"
notStartsWithOp = "not_starts_with" matchOp = "match"
endsWithOp = "ends_with"
notEndsWithOp = "not_ends_with"
matchOp = "match"
notMatchOp = "not_match"
) )
func operatorError(operator string) error { func operatorError(operator string) error {
...@@ -65,16 +61,12 @@ func operatorError(operator string) error { ...@@ -65,16 +61,12 @@ func operatorError(operator string) error {
type ifCondition func(string, string) bool type ifCondition func(string, string) bool
var ifConditions = map[string]ifCondition{ var ifConditions = map[string]ifCondition{
isOp: isFunc, isOp: isFunc,
notOp: notFunc, notOp: notFunc,
hasOp: hasFunc, hasOp: hasFunc,
notHasOp: notHasFunc, startsWithOp: startsWithFunc,
startsWithOp: startsWithFunc, endsWithOp: endsWithFunc,
notStartsWithOp: notStartsWithFunc, matchOp: matchFunc,
endsWithOp: endsWithFunc,
notEndsWithOp: notEndsWithFunc,
matchOp: matchFunc,
notMatchOp: notMatchFunc,
} }
// isFunc is condition for Is operator. // isFunc is condition for Is operator.
...@@ -95,36 +87,18 @@ func hasFunc(a, b string) bool { ...@@ -95,36 +87,18 @@ func hasFunc(a, b string) bool {
return strings.Contains(a, b) return strings.Contains(a, b)
} }
// notHasFunc is condition for NotHas operator.
// It checks if b is not a substring of a.
func notHasFunc(a, b string) bool {
return !hasFunc(a, b)
}
// startsWithFunc is condition for StartsWith operator. // startsWithFunc is condition for StartsWith operator.
// It checks if b is a prefix of a. // It checks if b is a prefix of a.
func startsWithFunc(a, b string) bool { func startsWithFunc(a, b string) bool {
return strings.HasPrefix(a, b) return strings.HasPrefix(a, b)
} }
// notStartsWithFunc is condition for NotStartsWith operator.
// It checks if b is not a prefix of a.
func notStartsWithFunc(a, b string) bool {
return !startsWithFunc(a, b)
}
// endsWithFunc is condition for EndsWith operator. // endsWithFunc is condition for EndsWith operator.
// It checks if b is a suffix of a. // It checks if b is a suffix of a.
func endsWithFunc(a, b string) bool { func endsWithFunc(a, b string) bool {
return strings.HasSuffix(a, b) return strings.HasSuffix(a, b)
} }
// notEndsWithFunc is condition for NotEndsWith operator.
// It checks if b is not a suffix of a.
func notEndsWithFunc(a, b string) bool {
return !endsWithFunc(a, b)
}
// matchFunc is condition for Match operator. // matchFunc is condition for Match operator.
// It does regexp matching of a against pattern in b // It does regexp matching of a against pattern in b
// and returns if they match. // and returns if they match.
...@@ -133,29 +107,29 @@ func matchFunc(a, b string) bool { ...@@ -133,29 +107,29 @@ func matchFunc(a, b string) bool {
return matched return matched
} }
// notMatchFunc is condition for NotMatch operator.
// It does regexp matching of a against pattern in b
// and returns if they do not match.
func notMatchFunc(a, b string) bool {
return !matchFunc(a, b)
}
// ifCond is statement for a IfMatcher condition. // ifCond is statement for a IfMatcher condition.
type ifCond struct { type ifCond struct {
a string a string
op string op string
b string b string
neg bool
} }
// newIfCond creates a new If condition. // newIfCond creates a new If condition.
func newIfCond(a, operator, b string) (ifCond, error) { func newIfCond(a, operator, b string) (ifCond, error) {
neg := false
if strings.HasPrefix(operator, "not_") {
neg = true
operator = operator[4:]
}
if _, ok := ifConditions[operator]; !ok { if _, ok := ifConditions[operator]; !ok {
return ifCond{}, operatorError(operator) return ifCond{}, operatorError(operator)
} }
return ifCond{ return ifCond{
a: a, a: a,
op: operator, op: operator,
b: b, b: b,
neg: neg,
}, nil }, nil
} }
...@@ -169,9 +143,12 @@ func (i ifCond) True(r *http.Request) bool { ...@@ -169,9 +143,12 @@ func (i ifCond) True(r *http.Request) bool {
a = replacer.Replace(i.a) a = replacer.Replace(i.a)
b = replacer.Replace(i.b) b = replacer.Replace(i.b)
} }
if i.neg {
return !c(a, b)
}
return c(a, b) return c(a, b)
} }
return false return i.neg // false if not negated, true otherwise
} }
// IfMatcher is a RequestMatcher for 'if' conditions. // IfMatcher is a RequestMatcher for 'if' conditions.
......
...@@ -201,7 +201,7 @@ func TestSetupIfMatcher(t *testing.T) { ...@@ -201,7 +201,7 @@ func TestSetupIfMatcher(t *testing.T) {
if a match b if a match b
}`, false, IfMatcher{ }`, false, IfMatcher{
ifs: []ifCond{ ifs: []ifCond{
{a: "a", op: "match", b: "b"}, {a: "a", op: "match", b: "b", neg: false},
}, },
}}, }},
{`test { {`test {
...@@ -209,7 +209,7 @@ func TestSetupIfMatcher(t *testing.T) { ...@@ -209,7 +209,7 @@ func TestSetupIfMatcher(t *testing.T) {
if_op or if_op or
}`, false, IfMatcher{ }`, false, IfMatcher{
ifs: []ifCond{ ifs: []ifCond{
{a: "a", op: "match", b: "b"}, {a: "a", op: "match", b: "b", neg: false},
}, },
isOr: true, isOr: true,
}}, }},
...@@ -230,8 +230,8 @@ func TestSetupIfMatcher(t *testing.T) { ...@@ -230,8 +230,8 @@ func TestSetupIfMatcher(t *testing.T) {
if cook not_has go if cook not_has go
}`, false, IfMatcher{ }`, false, IfMatcher{
ifs: []ifCond{ ifs: []ifCond{
{a: "goal", op: "has", b: "go"}, {a: "goal", op: "has", b: "go", neg: false},
{a: "cook", op: "not_has", b: "go"}, {a: "cook", op: "has", b: "go", neg: true},
}, },
}}, }},
{`test { {`test {
...@@ -240,8 +240,8 @@ func TestSetupIfMatcher(t *testing.T) { ...@@ -240,8 +240,8 @@ func TestSetupIfMatcher(t *testing.T) {
if_op and if_op and
}`, false, IfMatcher{ }`, false, IfMatcher{
ifs: []ifCond{ ifs: []ifCond{
{a: "goal", op: "has", b: "go"}, {a: "goal", op: "has", b: "go", neg: false},
{a: "cook", op: "not_has", b: "go"}, {a: "cook", op: "has", b: "go", neg: true},
}, },
}}, }},
{`test { {`test {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment