|
|
package matcher
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"reflect"
|
|
|
"strings"
|
|
|
|
|
|
ctxpkg "github.com/noahlann/nnet/pkg/context"
|
|
|
routerpkg "github.com/noahlann/nnet/pkg/router"
|
|
|
)
|
|
|
|
|
|
// FrameDataMatcher 帧数据匹配器
|
|
|
type FrameDataMatcher struct {
|
|
|
path string
|
|
|
operator string
|
|
|
value interface{}
|
|
|
priority int
|
|
|
}
|
|
|
|
|
|
// NewFrameDataMatcher 创建帧数据匹配器
|
|
|
func NewFrameDataMatcher(path, operator string, value interface{}) routerpkg.Matcher {
|
|
|
return &FrameDataMatcher{
|
|
|
path: path,
|
|
|
operator: operator,
|
|
|
value: value,
|
|
|
priority: 150, // 帧数据匹配优先级低于帧头匹配
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// WithPriority 设置优先级
|
|
|
func (m *FrameDataMatcher) WithPriority(priority int) *FrameDataMatcher {
|
|
|
m.priority = priority
|
|
|
return m
|
|
|
}
|
|
|
|
|
|
// Match 匹配帧数据
|
|
|
func (m *FrameDataMatcher) Match(input routerpkg.MatchInput, ctx ctxpkg.Context) bool {
|
|
|
var parsedData interface{}
|
|
|
if input.Data != nil {
|
|
|
parsedData = input.Data
|
|
|
} else if len(input.DataBytes) > 0 {
|
|
|
var jsonData map[string]interface{}
|
|
|
if err := json.Unmarshal(input.DataBytes, &jsonData); err != nil {
|
|
|
return false
|
|
|
}
|
|
|
parsedData = jsonData
|
|
|
} else if len(input.Raw) > 0 {
|
|
|
var jsonData map[string]interface{}
|
|
|
if err := json.Unmarshal(input.Raw, &jsonData); err != nil {
|
|
|
return false
|
|
|
}
|
|
|
parsedData = jsonData
|
|
|
} else if req := ctx.Request(); req != nil {
|
|
|
if req.Data() != nil {
|
|
|
parsedData = req.Data()
|
|
|
} else if len(req.DataBytes()) > 0 {
|
|
|
var jsonData map[string]interface{}
|
|
|
if err := json.Unmarshal(req.DataBytes(), &jsonData); err != nil {
|
|
|
return false
|
|
|
}
|
|
|
parsedData = jsonData
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if parsedData == nil {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// 根据路径提取值
|
|
|
fieldValue := m.extractValue(parsedData, m.path)
|
|
|
if fieldValue == nil {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
return m.compare(fieldValue, m.value, m.operator)
|
|
|
}
|
|
|
|
|
|
// extractValue 从数据中提取值(支持点号分隔的路径,如 "user.id")
|
|
|
func (m *FrameDataMatcher) extractValue(data interface{}, path string) interface{} {
|
|
|
if path == "" {
|
|
|
return data
|
|
|
}
|
|
|
|
|
|
parts := strings.Split(path, ".")
|
|
|
current := data
|
|
|
|
|
|
for _, part := range parts {
|
|
|
switch v := current.(type) {
|
|
|
case map[string]interface{}:
|
|
|
current = v[part]
|
|
|
if current == nil {
|
|
|
return nil
|
|
|
}
|
|
|
default:
|
|
|
// 使用反射获取字段值
|
|
|
rv := reflect.ValueOf(current)
|
|
|
if rv.Kind() == reflect.Ptr {
|
|
|
rv = rv.Elem()
|
|
|
}
|
|
|
if rv.Kind() != reflect.Struct {
|
|
|
return nil
|
|
|
}
|
|
|
field := rv.FieldByName(part)
|
|
|
if !field.IsValid() {
|
|
|
return nil
|
|
|
}
|
|
|
current = field.Interface()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return current
|
|
|
}
|
|
|
|
|
|
// compare 比较值(与FrameHeaderMatcher相同的逻辑)
|
|
|
func (m *FrameDataMatcher) compare(actual, expected interface{}, operator string) bool {
|
|
|
switch operator {
|
|
|
case "==":
|
|
|
return reflect.DeepEqual(actual, expected)
|
|
|
case "!=":
|
|
|
return !reflect.DeepEqual(actual, expected)
|
|
|
case ">":
|
|
|
return m.greaterThan(actual, expected)
|
|
|
case "<":
|
|
|
return m.lessThan(actual, expected)
|
|
|
case ">=":
|
|
|
return m.greaterThan(actual, expected) || reflect.DeepEqual(actual, expected)
|
|
|
case "<=":
|
|
|
return m.lessThan(actual, expected) || reflect.DeepEqual(actual, expected)
|
|
|
case "in":
|
|
|
return m.in(actual, expected)
|
|
|
case "contains":
|
|
|
return m.contains(actual, expected)
|
|
|
default:
|
|
|
return false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// greaterThan 大于比较
|
|
|
func (m *FrameDataMatcher) greaterThan(a, b interface{}) bool {
|
|
|
switch av := a.(type) {
|
|
|
case int:
|
|
|
if bv, ok := b.(int); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case int32:
|
|
|
if bv, ok := b.(int32); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case int64:
|
|
|
if bv, ok := b.(int64); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case uint8:
|
|
|
if bv, ok := b.(uint8); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case uint32:
|
|
|
if bv, ok := b.(uint32); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case uint64:
|
|
|
if bv, ok := b.(uint64); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
case float64:
|
|
|
if bv, ok := b.(float64); ok {
|
|
|
return av > bv
|
|
|
}
|
|
|
}
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// lessThan 小于比较
|
|
|
func (m *FrameDataMatcher) lessThan(a, b interface{}) bool {
|
|
|
switch av := a.(type) {
|
|
|
case int:
|
|
|
if bv, ok := b.(int); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case int32:
|
|
|
if bv, ok := b.(int32); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case int64:
|
|
|
if bv, ok := b.(int64); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case uint8:
|
|
|
if bv, ok := b.(uint8); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case uint32:
|
|
|
if bv, ok := b.(uint32); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case uint64:
|
|
|
if bv, ok := b.(uint64); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
case float64:
|
|
|
if bv, ok := b.(float64); ok {
|
|
|
return av < bv
|
|
|
}
|
|
|
}
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// in 检查是否在列表中
|
|
|
func (m *FrameDataMatcher) in(value, list interface{}) bool {
|
|
|
listValue := reflect.ValueOf(list)
|
|
|
if listValue.Kind() != reflect.Slice {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
for i := 0; i < listValue.Len(); i++ {
|
|
|
if reflect.DeepEqual(value, listValue.Index(i).Interface()) {
|
|
|
return true
|
|
|
}
|
|
|
}
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// contains 检查是否包含
|
|
|
func (m *FrameDataMatcher) contains(container, item interface{}) bool {
|
|
|
// 字符串包含
|
|
|
if str, ok := container.(string); ok {
|
|
|
if itemStr, ok := item.(string); ok {
|
|
|
return strings.Contains(str, itemStr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 数组/切片包含
|
|
|
containerValue := reflect.ValueOf(container)
|
|
|
if containerValue.Kind() == reflect.Slice {
|
|
|
for i := 0; i < containerValue.Len(); i++ {
|
|
|
if reflect.DeepEqual(item, containerValue.Index(i).Interface()) {
|
|
|
return true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// Priority 获取优先级
|
|
|
func (m *FrameDataMatcher) Priority() int {
|
|
|
return m.priority
|
|
|
}
|
|
|
|
|
|
// Path 获取路径
|
|
|
func (m *FrameDataMatcher) Path() string {
|
|
|
return m.path
|
|
|
}
|
|
|
|
|
|
// Operator 获取操作符
|
|
|
func (m *FrameDataMatcher) Operator() string {
|
|
|
return m.operator
|
|
|
}
|
|
|
|
|
|
// Value 获取匹配值
|
|
|
func (m *FrameDataMatcher) Value() interface{} {
|
|
|
return m.value
|
|
|
}
|