You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
3.4 KiB
Go
172 lines
3.4 KiB
Go
package matcher
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
ctxpkg "github.com/noahlann/nnet/pkg/context"
|
|
routerpkg "github.com/noahlann/nnet/pkg/router"
|
|
)
|
|
|
|
// FrameHeaderMatcher 帧头匹配器
|
|
type FrameHeaderMatcher struct {
|
|
field string
|
|
operator string
|
|
value interface{}
|
|
priority int
|
|
}
|
|
|
|
// NewFrameHeaderMatcher 创建帧头匹配器
|
|
func NewFrameHeaderMatcher(field, operator string, value interface{}) *FrameHeaderMatcher {
|
|
return &FrameHeaderMatcher{
|
|
field: field,
|
|
operator: operator,
|
|
value: value,
|
|
priority: 200, // 帧头匹配优先级高于字符串匹配
|
|
}
|
|
}
|
|
|
|
// WithPriority 设置优先级
|
|
func (m *FrameHeaderMatcher) WithPriority(priority int) *FrameHeaderMatcher {
|
|
m.priority = priority
|
|
return m
|
|
}
|
|
|
|
// Match 匹配帧头
|
|
func (m *FrameHeaderMatcher) Match(input routerpkg.MatchInput, ctx ctxpkg.Context) bool {
|
|
header := input.Header
|
|
if header == nil {
|
|
if req := ctx.Request(); req != nil {
|
|
header = req.Header()
|
|
}
|
|
}
|
|
if header == nil {
|
|
return false
|
|
}
|
|
|
|
fieldValue := header.Get(m.field)
|
|
if fieldValue == nil {
|
|
return false
|
|
}
|
|
|
|
return m.compare(fieldValue, m.value, m.operator)
|
|
}
|
|
|
|
// compare 比较值
|
|
func (m *FrameHeaderMatcher) 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)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// greaterThan 大于比较
|
|
func (m *FrameHeaderMatcher) 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
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// lessThan 小于比较
|
|
func (m *FrameHeaderMatcher) 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
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// in 检查是否在列表中
|
|
func (m *FrameHeaderMatcher) 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
|
|
}
|
|
|
|
// Priority 获取优先级
|
|
func (m *FrameHeaderMatcher) Priority() int {
|
|
return m.priority
|
|
}
|
|
|
|
// Field 获取字段名
|
|
func (m *FrameHeaderMatcher) Field() string {
|
|
return m.field
|
|
}
|
|
|
|
// Operator 获取操作符
|
|
func (m *FrameHeaderMatcher) Operator() string {
|
|
return m.operator
|
|
}
|
|
|
|
// Value 获取匹配值
|
|
func (m *FrameHeaderMatcher) Value() interface{} {
|
|
return m.value
|
|
}
|