refactor(matcher): 提取 LocationType 常量并优化结构体字段布局
- 添加 LocationType 常量定义替代硬编码字符串 - 优化 MatchResult、ExactMatcher、NamedMatcher 结构体字段顺序 - RadixTree.Insert 添加 locationType 参数用于调试追踪 - 更新测试代码适配新接口 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
c418baeb90
commit
ca03c121d3
@ -19,7 +19,7 @@ func BenchmarkRadixTree_Insert(b *testing.B) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
tree.Insert(p, handler, i)
|
tree.Insert(p, handler, i, "prefix")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ func BenchmarkRadixTree_Find(b *testing.B) {
|
|||||||
|
|
||||||
paths := []string{"/", "/api", "/api/v1", "/api/v2/users/123"}
|
paths := []string{"/", "/api", "/api/v1", "/api/v2/users/123"}
|
||||||
for i, p := range paths {
|
for i, p := range paths {
|
||||||
tree.Insert(p, handler, i+1)
|
tree.Insert(p, handler, i+1, "prefix")
|
||||||
}
|
}
|
||||||
tree.MarkInitialized()
|
tree.MarkInitialized()
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import (
|
|||||||
|
|
||||||
// ExactMatcher Hash Map 精确匹配
|
// ExactMatcher Hash Map 精确匹配
|
||||||
type ExactMatcher struct {
|
type ExactMatcher struct {
|
||||||
path string
|
|
||||||
handler fasthttp.RequestHandler
|
handler fasthttp.RequestHandler
|
||||||
|
path string
|
||||||
priority int
|
priority int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +31,6 @@ func (m *ExactMatcher) Result() *MatchResult {
|
|||||||
Handler: m.handler,
|
Handler: m.handler,
|
||||||
Path: m.path,
|
Path: m.path,
|
||||||
Priority: m.priority,
|
Priority: m.priority,
|
||||||
LocationType: "exact",
|
LocationType: LocationTypeExact,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ func TestLocationEngine_NginxPriority(t *testing.T) {
|
|||||||
|
|
||||||
// 测试 ^~ 阻止正则
|
// 测试 ^~ 阻止正则
|
||||||
result = engine.Match("/api/test.php")
|
result = engine.Match("/api/test.php")
|
||||||
if result.LocationType != "prefix" {
|
if result.LocationType != "prefix_priority" {
|
||||||
t.Errorf("^~ should block regex, got %s", result.LocationType)
|
t.Errorf("^~ should block regex, got %s", result.LocationType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,24 +10,13 @@ import (
|
|||||||
|
|
||||||
// LocationEngine 统一匹配引擎
|
// LocationEngine 统一匹配引擎
|
||||||
type LocationEngine struct {
|
type LocationEngine struct {
|
||||||
// 精确匹配 - Hash Map (O(1))
|
|
||||||
exactMatchers map[string]*ExactMatcher
|
|
||||||
|
|
||||||
// 前缀匹配 - Radix Tree (O(log n))
|
|
||||||
prefixPriorityTree *RadixTree // ^~ 类型(优先级 2)
|
prefixPriorityTree *RadixTree // ^~ 类型(优先级 2)
|
||||||
prefixTree *RadixTree // 普通前缀(优先级 4)
|
prefixTree *RadixTree // 普通前缀(优先级 4)
|
||||||
|
exactMatchers map[string]*ExactMatcher
|
||||||
// 正则匹配 - Linear Scan(按配置顺序)
|
namedMatchers map[string]*NamedMatcher
|
||||||
regexMatchers []*RegexMatcher
|
registeredPaths map[string]string
|
||||||
|
regexMatchers []*RegexMatcher
|
||||||
// 命名 location - Hash Map
|
initialized bool
|
||||||
namedMatchers map[string]*NamedMatcher
|
|
||||||
|
|
||||||
// 初始化标记
|
|
||||||
initialized bool
|
|
||||||
|
|
||||||
// 冲突检测
|
|
||||||
registeredPaths map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLocationEngine 创建新引擎
|
// NewLocationEngine 创建新引擎
|
||||||
@ -67,7 +56,7 @@ func (e *LocationEngine) AddPrefixPriority(path string, handler fasthttp.Request
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.prefixPriorityTree.Insert(path, handler, 2)
|
return e.prefixPriorityTree.Insert(path, handler, 2, "prefix_priority")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRegex 添加正则匹配 location
|
// AddRegex 添加正则匹配 location
|
||||||
@ -95,7 +84,7 @@ func (e *LocationEngine) AddPrefix(path string, handler fasthttp.RequestHandler)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.prefixTree.Insert(path, handler, 4)
|
return e.prefixTree.Insert(path, handler, 4, "prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNamed 添加命名 location
|
// AddNamed 添加命名 location
|
||||||
|
|||||||
@ -2,15 +2,23 @@ package matcher
|
|||||||
|
|
||||||
import "github.com/valyala/fasthttp"
|
import "github.com/valyala/fasthttp"
|
||||||
|
|
||||||
|
// LocationType 常量定义
|
||||||
|
const (
|
||||||
|
LocationTypeExact = "exact"
|
||||||
|
LocationTypePrefix = "prefix"
|
||||||
|
LocationTypePrefixPriority = "prefix_priority"
|
||||||
|
LocationTypeRegex = "regex"
|
||||||
|
LocationTypeRegexCaseless = "regex_caseless"
|
||||||
|
LocationTypeNamed = "named"
|
||||||
|
)
|
||||||
|
|
||||||
// MatchResult 匹配结果
|
// MatchResult 匹配结果
|
||||||
type MatchResult struct {
|
type MatchResult struct {
|
||||||
|
Captures map[string]string // 正则捕获组
|
||||||
Handler fasthttp.RequestHandler
|
Handler fasthttp.RequestHandler
|
||||||
|
LocationType string
|
||||||
Path string
|
Path string
|
||||||
Priority int
|
Priority int
|
||||||
LocationType string
|
|
||||||
|
|
||||||
// 正则捕获组
|
|
||||||
Captures map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matcher 接口
|
// Matcher 接口
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import "github.com/valyala/fasthttp"
|
|||||||
|
|
||||||
// NamedMatcher @命名 location
|
// NamedMatcher @命名 location
|
||||||
type NamedMatcher struct {
|
type NamedMatcher struct {
|
||||||
name string
|
|
||||||
handler fasthttp.RequestHandler
|
handler fasthttp.RequestHandler
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNamedMatcher 创建命名匹配器
|
// NewNamedMatcher 创建命名匹配器
|
||||||
@ -17,7 +17,7 @@ func NewNamedMatcher(name string, handler fasthttp.RequestHandler) *NamedMatcher
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match 检查命名是否匹配(命名 location 不使用 path 匹配)
|
// Match 检查命名是否匹配(命名 location 不使用 path 匹配)
|
||||||
func (m *NamedMatcher) Match(path string) bool {
|
func (m *NamedMatcher) Match(_ string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ func (m *NamedMatcher) Result() *MatchResult {
|
|||||||
Handler: m.handler,
|
Handler: m.handler,
|
||||||
Path: "@" + m.name,
|
Path: "@" + m.name,
|
||||||
Priority: 0,
|
Priority: 0,
|
||||||
LocationType: "named",
|
LocationType: LocationTypeNamed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ func NewPrefixMatcher() *PrefixMatcher {
|
|||||||
|
|
||||||
// AddPath 添加路径
|
// AddPath 添加路径
|
||||||
func (pm *PrefixMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
func (pm *PrefixMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
||||||
return pm.tree.Insert(path, handler, pm.priority)
|
return pm.tree.Insert(path, handler, pm.priority, "prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match 前缀匹配,返回最长前缀匹配结果
|
// Match 前缀匹配,返回最长前缀匹配结果
|
||||||
|
|||||||
@ -18,7 +18,7 @@ func NewPrefixPriorityMatcher() *PrefixPriorityMatcher {
|
|||||||
|
|
||||||
// AddPath 添加路径
|
// AddPath 添加路径
|
||||||
func (ppm *PrefixPriorityMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
func (ppm *PrefixPriorityMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
||||||
return ppm.tree.Insert(path, handler, ppm.priority)
|
return ppm.tree.Insert(path, handler, ppm.priority, "prefix_priority")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match 前缀优先匹配,返回最长前缀匹配结果
|
// Match 前缀优先匹配,返回最长前缀匹配结果
|
||||||
|
|||||||
@ -9,11 +9,12 @@ import (
|
|||||||
|
|
||||||
// RadixNode Radix Tree 节点
|
// RadixNode Radix Tree 节点
|
||||||
type RadixNode struct {
|
type RadixNode struct {
|
||||||
prefix string
|
children []*RadixNode
|
||||||
handler fasthttp.RequestHandler
|
handler fasthttp.RequestHandler
|
||||||
children []*RadixNode
|
priority int
|
||||||
isLeaf bool
|
isLeaf bool
|
||||||
priority int
|
prefix string
|
||||||
|
locationType string // exact/prefix/prefix_priority
|
||||||
}
|
}
|
||||||
|
|
||||||
// RadixTree 前缀匹配 Radix Tree
|
// RadixTree 前缀匹配 Radix Tree
|
||||||
@ -30,29 +31,31 @@ func NewRadixTree() *RadixTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert 插入路径到 Radix Tree(startup-only)
|
// Insert 插入路径到 Radix Tree(startup-only)
|
||||||
func (t *RadixTree) Insert(path string, handler fasthttp.RequestHandler, priority int) error {
|
func (t *RadixTree) Insert(path string, handler fasthttp.RequestHandler, priority int, locationType string) error {
|
||||||
if t.initialized {
|
if t.initialized {
|
||||||
return errors.New("RadixTree already initialized")
|
return errors.New("RadixTree already initialized")
|
||||||
}
|
}
|
||||||
return t.insertNode(nil, t.root, path, handler, priority)
|
return t.insertNode(nil, t.root, path, handler, priority, locationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertNode 完整路径分割插入算法
|
// insertNode 完整路径分割插入算法
|
||||||
func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string, handler fasthttp.RequestHandler, priority int) error {
|
func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string, handler fasthttp.RequestHandler, priority int, locationType string) error {
|
||||||
// Case 1: 空节点(根节点),直接设置
|
// Case 1: 空节点(根节点),直接设置
|
||||||
if node.prefix == "" && len(node.children) == 0 && node.handler == nil {
|
if node.prefix == "" && len(node.children) == 0 && node.handler == nil {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
node.handler = handler
|
node.handler = handler
|
||||||
node.priority = priority
|
node.priority = priority
|
||||||
node.isLeaf = true
|
node.isLeaf = true
|
||||||
|
node.locationType = locationType
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// 创建新子节点
|
// 创建新子节点
|
||||||
newNode := &RadixNode{
|
newNode := &RadixNode{
|
||||||
prefix: path,
|
prefix: path,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
isLeaf: true,
|
isLeaf: true,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
|
locationType: locationType,
|
||||||
}
|
}
|
||||||
node.children = append(node.children, newNode)
|
node.children = append(node.children, newNode)
|
||||||
return nil
|
return nil
|
||||||
@ -77,22 +80,24 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
|||||||
node.handler = handler
|
node.handler = handler
|
||||||
node.priority = priority
|
node.priority = priority
|
||||||
node.isLeaf = true
|
node.isLeaf = true
|
||||||
|
node.locationType = locationType
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索匹配剩余路径的子节点
|
// 搜索匹配剩余路径的子节点
|
||||||
for _, child := range node.children {
|
for _, child := range node.children {
|
||||||
if strings.HasPrefix(remaining, child.prefix) {
|
if strings.HasPrefix(remaining, child.prefix) {
|
||||||
return t.insertNode(node, child, remaining, handler, priority)
|
return t.insertNode(node, child, remaining, handler, priority, locationType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 无匹配子节点,创建新子节点
|
// 无匹配子节点,创建新子节点
|
||||||
newNode := &RadixNode{
|
newNode := &RadixNode{
|
||||||
prefix: remaining,
|
prefix: remaining,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
isLeaf: true,
|
isLeaf: true,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
|
locationType: locationType,
|
||||||
}
|
}
|
||||||
node.children = append(node.children, newNode)
|
node.children = append(node.children, newNode)
|
||||||
return nil
|
return nil
|
||||||
@ -110,10 +115,11 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
|||||||
|
|
||||||
// 创建新节点保存剩余路径
|
// 创建新节点保存剩余路径
|
||||||
newNode := &RadixNode{
|
newNode := &RadixNode{
|
||||||
prefix: path[commonLen:],
|
prefix: path[commonLen:],
|
||||||
handler: handler,
|
handler: handler,
|
||||||
isLeaf: true,
|
isLeaf: true,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
|
locationType: locationType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将原节点和新节点作为 splitNode 的子节点
|
// 将原节点和新节点作为 splitNode 的子节点
|
||||||
@ -159,7 +165,7 @@ func (t *RadixTree) searchLongest(node *RadixNode, path string, bestMatch *Match
|
|||||||
Handler: node.handler,
|
Handler: node.handler,
|
||||||
Path: node.prefix,
|
Path: node.prefix,
|
||||||
Priority: node.priority,
|
Priority: node.priority,
|
||||||
LocationType: "prefix",
|
LocationType: node.locationType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// nil-safe 优先级比较 + 长度比较
|
// nil-safe 优先级比较 + 长度比较
|
||||||
|
|||||||
@ -11,7 +11,7 @@ func TestRadixTree_Insert_EmptyNode(t *testing.T) {
|
|||||||
tree := NewRadixTree()
|
tree := NewRadixTree()
|
||||||
handler := func(ctx *fasthttp.RequestCtx) {}
|
handler := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
err := tree.Insert("/api", handler, 1)
|
err := tree.Insert("/api", handler, 1, "prefix")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("insert failed: %v", err)
|
t.Fatalf("insert failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -31,8 +31,8 @@ func TestRadixTree_Insert_CommonPrefix(t *testing.T) {
|
|||||||
handler1 := func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("1") }
|
handler1 := func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("1") }
|
||||||
handler2 := func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("2") }
|
handler2 := func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("2") }
|
||||||
|
|
||||||
tree.Insert("/api", handler1, 1)
|
tree.Insert("/api", handler1, 1, "prefix")
|
||||||
tree.Insert("/api/users", handler2, 2)
|
tree.Insert("/api/users", handler2, 2, "prefix")
|
||||||
|
|
||||||
result := tree.FindLongestPrefix("/api/users")
|
result := tree.FindLongestPrefix("/api/users")
|
||||||
if result == nil {
|
if result == nil {
|
||||||
@ -53,8 +53,8 @@ func TestRadixTree_Insert_NodeSplit(t *testing.T) {
|
|||||||
handler1 := func(ctx *fasthttp.RequestCtx) {}
|
handler1 := func(ctx *fasthttp.RequestCtx) {}
|
||||||
handler2 := func(ctx *fasthttp.RequestCtx) {}
|
handler2 := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/abc", handler1, 1)
|
tree.Insert("/abc", handler1, 1, "prefix")
|
||||||
tree.Insert("/abx", handler2, 2)
|
tree.Insert("/abx", handler2, 2, "prefix")
|
||||||
|
|
||||||
// 应该正确分割 /ab 公共前缀
|
// 应该正确分割 /ab 公共前缀
|
||||||
result := tree.FindLongestPrefix("/abc")
|
result := tree.FindLongestPrefix("/abc")
|
||||||
@ -67,9 +67,9 @@ func TestRadixTree_FindLongestPrefix(t *testing.T) {
|
|||||||
tree := NewRadixTree()
|
tree := NewRadixTree()
|
||||||
handler := func(ctx *fasthttp.RequestCtx) {}
|
handler := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/", handler, 1)
|
tree.Insert("/", handler, 1, "prefix")
|
||||||
tree.Insert("/api", handler, 2)
|
tree.Insert("/api", handler, 2, "prefix")
|
||||||
tree.Insert("/api/v1", handler, 3)
|
tree.Insert("/api/v1", handler, 3, "prefix")
|
||||||
|
|
||||||
// "/" has priority 1 (wins), "/api" has 2, "/api/v1" has 3
|
// "/" has priority 1 (wins), "/api" has 2, "/api/v1" has 3
|
||||||
// Lower number = higher priority
|
// Lower number = higher priority
|
||||||
@ -86,10 +86,10 @@ func TestRadixTree_Insert_AfterInitialized(t *testing.T) {
|
|||||||
tree := NewRadixTree()
|
tree := NewRadixTree()
|
||||||
handler := func(ctx *fasthttp.RequestCtx) {}
|
handler := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/api", handler, 1)
|
tree.Insert("/api", handler, 1, "prefix")
|
||||||
tree.MarkInitialized()
|
tree.MarkInitialized()
|
||||||
|
|
||||||
err := tree.Insert("/api/v2", handler, 2)
|
err := tree.Insert("/api/v2", handler, 2, "prefix")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("should fail when inserting after initialized")
|
t.Error("should fail when inserting after initialized")
|
||||||
}
|
}
|
||||||
@ -99,8 +99,8 @@ func TestRadixTree_Insert_DuplicatePath(t *testing.T) {
|
|||||||
tree := NewRadixTree()
|
tree := NewRadixTree()
|
||||||
handler := func(ctx *fasthttp.RequestCtx) {}
|
handler := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/api", handler, 1)
|
tree.Insert("/api", handler, 1, "prefix")
|
||||||
err := tree.Insert("/api", handler, 2)
|
err := tree.Insert("/api", handler, 2, "prefix")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("should fail on duplicate path")
|
t.Error("should fail on duplicate path")
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ func TestRadixTree_FindLongestPrefix_NoMatch(t *testing.T) {
|
|||||||
tree := NewRadixTree()
|
tree := NewRadixTree()
|
||||||
handler := func(ctx *fasthttp.RequestCtx) {}
|
handler := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/api", handler, 1)
|
tree.Insert("/api", handler, 1, "prefix")
|
||||||
|
|
||||||
result := tree.FindLongestPrefix("/other")
|
result := tree.FindLongestPrefix("/other")
|
||||||
if result != nil {
|
if result != nil {
|
||||||
@ -123,8 +123,8 @@ func TestRadixTree_PriorityComparison(t *testing.T) {
|
|||||||
h1 := func(ctx *fasthttp.RequestCtx) {}
|
h1 := func(ctx *fasthttp.RequestCtx) {}
|
||||||
h2 := func(ctx *fasthttp.RequestCtx) {}
|
h2 := func(ctx *fasthttp.RequestCtx) {}
|
||||||
|
|
||||||
tree.Insert("/api", h1, 5)
|
tree.Insert("/api", h1, 5, "prefix")
|
||||||
tree.Insert("/api/users", h2, 2)
|
tree.Insert("/api/users", h2, 2, "prefix")
|
||||||
|
|
||||||
// Lower priority number wins
|
// Lower priority number wins
|
||||||
result := tree.FindLongestPrefix("/api/users")
|
result := tree.FindLongestPrefix("/api/users")
|
||||||
@ -135,3 +135,24 @@ func TestRadixTree_PriorityComparison(t *testing.T) {
|
|||||||
t.Errorf("expected priority 2, got %d", result.Priority)
|
t.Errorf("expected priority 2, got %d", result.Priority)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRadixTree_Insert_ExactMatch(t *testing.T) {
|
||||||
|
// Case 3: path 完全匹配节点前缀,设置 handler
|
||||||
|
tree := NewRadixTree()
|
||||||
|
handler := func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("exact") }
|
||||||
|
|
||||||
|
// 先插入父路径
|
||||||
|
tree.Insert("/api", handler, 1, "prefix")
|
||||||
|
|
||||||
|
// 再次插入相同路径(应该报错重复)
|
||||||
|
err := tree.Insert("/api", handler, 2, "prefix")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("should return error for duplicate path")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证原 handler 未被覆盖
|
||||||
|
result := tree.FindLongestPrefix("/api")
|
||||||
|
if result == nil || result.Priority != 1 {
|
||||||
|
t.Errorf("original handler should not be overwritten, got priority %d", result.Priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import (
|
|||||||
type RegexMatcher struct {
|
type RegexMatcher struct {
|
||||||
pattern *regexp.Regexp
|
pattern *regexp.Regexp
|
||||||
handler fasthttp.RequestHandler
|
handler fasthttp.RequestHandler
|
||||||
|
captures map[string]string
|
||||||
priority int
|
priority int
|
||||||
caseInsensitive bool
|
caseInsensitive bool
|
||||||
captures map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegexMatcher 创建正则匹配器
|
// NewRegexMatcher 创建正则匹配器
|
||||||
@ -47,9 +47,9 @@ func (m *RegexMatcher) Match(path string) bool {
|
|||||||
|
|
||||||
// Result 返回匹配结果
|
// Result 返回匹配结果
|
||||||
func (m *RegexMatcher) Result() *MatchResult {
|
func (m *RegexMatcher) Result() *MatchResult {
|
||||||
locType := "regex"
|
locType := LocationTypeRegex
|
||||||
if m.caseInsensitive {
|
if m.caseInsensitive {
|
||||||
locType = "regex_caseless"
|
locType = LocationTypeRegexCaseless
|
||||||
}
|
}
|
||||||
return &MatchResult{
|
return &MatchResult{
|
||||||
Handler: m.handler,
|
Handler: m.handler,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user