matcher.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package model
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "go-common/app/service/live/zeus/expr"
  7. "go-common/library/log"
  8. )
  9. type Matcher struct {
  10. Group map[string][]*MatcherBucket `json:"group"`
  11. VariableWhitelist []string `json:"variable_whitelist"`
  12. }
  13. type MatcherBucket struct {
  14. RuleExpr string `json:"expr"`
  15. Extend interface{} `json:"extend"`
  16. expr expr.Expr
  17. variable []string
  18. config string
  19. }
  20. func NewMatcher(config string) (*Matcher, error) {
  21. matcher := &Matcher{}
  22. if err := json.Unmarshal([]byte(config), matcher); err != nil {
  23. return nil, err
  24. }
  25. whitelist := make(map[string]struct{}, len(matcher.VariableWhitelist))
  26. for _, v := range matcher.VariableWhitelist {
  27. whitelist[v] = struct{}{}
  28. }
  29. parser := expr.NewExpressionParser()
  30. for _, bucket := range matcher.Group {
  31. for _, b := range bucket {
  32. if e := parser.Parse(b.RuleExpr); e != nil {
  33. msg := fmt.Sprintf("zeus compile error, rule:%s error:%s", b.RuleExpr, e.Error())
  34. return nil, errors.New(msg)
  35. }
  36. b.expr = parser.GetExpr()
  37. b.variable = parser.GetVariable()
  38. for _, v := range b.variable {
  39. if _, ok := whitelist[v]; !ok {
  40. msg := fmt.Sprintf("zeus check error, rule:%s error: variable %s not in whitelist", b.RuleExpr, v)
  41. return nil, errors.New(msg)
  42. }
  43. }
  44. if config, e := json.Marshal(b.Extend); e != nil {
  45. msg := fmt.Sprintf("zeus parse config error, rule:%s error:%s", b.RuleExpr, e.Error())
  46. return nil, errors.New(msg)
  47. } else {
  48. b.config = string(config)
  49. }
  50. }
  51. }
  52. return matcher, nil
  53. }
  54. func (m *Matcher) Match(group string, env expr.Env) (bool, string, error) {
  55. var bucket []*MatcherBucket
  56. var ok bool
  57. if bucket, ok = m.Group[group]; !ok {
  58. return false, "", errors.New("group not found")
  59. }
  60. isMatch := false
  61. extend := ""
  62. for _, b := range bucket {
  63. result, err := expr.EvalBool(b.expr, env)
  64. if err != nil {
  65. log.Error("zeus eval error, group:%s expr:%s error:%s", group, b.RuleExpr, err.Error())
  66. continue
  67. }
  68. if result {
  69. isMatch = true
  70. extend = b.config
  71. break
  72. }
  73. }
  74. return isMatch, extend, nil
  75. }