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.

91 lines
2.5 KiB
Go

package router
import (
"sort"
"sync"
"github.com/noahlann/nnet/internal/router/matcher"
ctxpkg "github.com/noahlann/nnet/pkg/context"
"github.com/noahlann/nnet/pkg/errors"
"github.com/noahlann/nnet/pkg/router"
)
// routerImpl 路由器实现
type routerImpl struct {
routes []*route
mu sync.RWMutex
}
// NewRouter 创建新路由器
func NewRouter() router.Router {
return &routerImpl{
routes: make([]*route, 0),
}
}
// Register 注册路由
func (r *routerImpl) Register(matcher router.Matcher, handler router.Handler, opts ...router.RouteOption) router.Route {
r.mu.Lock()
defer r.mu.Unlock()
// 应用路由选项
config := &router.RouteConfig{}
for _, opt := range opts {
opt(config)
}
rt := newRoute(matcher, handler, config)
r.routes = append(r.routes, rt)
// 按优先级排序(优先级高的在前)
sort.Slice(r.routes, func(i, j int) bool {
return r.routes[i].matcher.Priority() > r.routes[j].matcher.Priority()
})
return rt
}
// RegisterString 注册字符串路由
func (r *routerImpl) RegisterString(pattern string, handler router.Handler, opts ...router.RouteOption) router.Route {
matcher := router.NewStringMatcher(pattern)
return r.Register(matcher, handler, opts...)
}
// RegisterFrameHeader 注册帧头匹配路由
func (r *routerImpl) RegisterFrameHeader(field, operator string, value interface{}, handler router.Handler, opts ...router.RouteOption) router.Route {
m := matcher.NewFrameHeaderMatcher(field, operator, value)
return r.Register(m, handler, opts...)
}
// RegisterFrameData 注册帧数据匹配路由
func (r *routerImpl) RegisterFrameData(path, operator string, value interface{}, handler router.Handler, opts ...router.RouteOption) router.Route {
m := matcher.NewFrameDataMatcher(path, operator, value)
return r.Register(m, handler, opts...)
}
// RegisterCustom 注册自定义匹配路由
func (r *routerImpl) RegisterCustom(fn func(input router.MatchInput, ctx ctxpkg.Context) bool, handler router.Handler, opts ...router.RouteOption) router.Route {
m := router.NewCustomMatcher(fn)
return r.Register(m, handler, opts...)
}
// Group 创建路由分组
func (r *routerImpl) Group() router.RouterGroup {
return newRouterGroup(r, "")
}
// Match 匹配路由
func (r *routerImpl) Match(input router.MatchInput, ctx ctxpkg.Context) (router.Route, router.Handler, error) {
r.mu.RLock()
defer r.mu.RUnlock()
// 按优先级顺序匹配
for _, route := range r.routes {
if route.matcher.Match(input, ctx) {
return route, route.Handler(), nil
}
}
return nil, nil, errors.ErrRouteNotFound
}