feat(matcher): 支持 internal location 标记
- MatchResult 新增 Internal 字段 - AddExact/AddPrefix/AddPrefixPriority/AddRadix/AddRegex 方法新增 internal 参数 - location 解析器支持 internal 指令 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e05cf8a674
commit
65080cca66
@ -15,6 +15,9 @@ type ExactMatcher struct {
|
||||
// handler 请求处理器
|
||||
handler fasthttp.RequestHandler
|
||||
|
||||
// internal 是否为 internal location
|
||||
internal bool
|
||||
|
||||
// path 精确匹配路径
|
||||
path string
|
||||
|
||||
@ -28,14 +31,16 @@ type ExactMatcher struct {
|
||||
// - path: 精确匹配的路径
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - priority: 优先级(通常设为 1)
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - *ExactMatcher: 精确匹配器实例
|
||||
func NewExactMatcher(path string, handler fasthttp.RequestHandler, priority int) *ExactMatcher {
|
||||
func NewExactMatcher(path string, handler fasthttp.RequestHandler, priority int, internal bool) *ExactMatcher {
|
||||
return &ExactMatcher{
|
||||
path: path,
|
||||
handler: handler,
|
||||
priority: priority,
|
||||
internal: internal,
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,5 +65,6 @@ func (m *ExactMatcher) Result() *MatchResult {
|
||||
Path: m.path,
|
||||
Priority: m.priority,
|
||||
LocationType: LocationTypeExact,
|
||||
Internal: m.internal,
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,10 +74,11 @@ func NewLocationEngine() *LocationEngine {
|
||||
// 参数:
|
||||
// - path: 精确匹配路径
|
||||
// - handler: 请求处理器
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 引擎已初始化或路径冲突时返回错误
|
||||
func (e *LocationEngine) AddExact(path string, handler fasthttp.RequestHandler) error {
|
||||
func (e *LocationEngine) AddExact(path string, handler fasthttp.RequestHandler, internal bool) error {
|
||||
if e.initialized {
|
||||
return errors.New("LocationEngine already initialized")
|
||||
}
|
||||
@ -86,7 +87,7 @@ func (e *LocationEngine) AddExact(path string, handler fasthttp.RequestHandler)
|
||||
return err
|
||||
}
|
||||
|
||||
matcher := NewExactMatcher(path, handler, 1)
|
||||
matcher := NewExactMatcher(path, handler, 1, internal)
|
||||
e.exactMatchers[path] = matcher
|
||||
return nil
|
||||
}
|
||||
@ -96,10 +97,11 @@ func (e *LocationEngine) AddExact(path string, handler fasthttp.RequestHandler)
|
||||
// 参数:
|
||||
// - path: 前缀优先路径
|
||||
// - handler: 请求处理器
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 引擎已初始化或路径冲突时返回错误
|
||||
func (e *LocationEngine) AddPrefixPriority(path string, handler fasthttp.RequestHandler) error {
|
||||
func (e *LocationEngine) AddPrefixPriority(path string, handler fasthttp.RequestHandler, internal bool) error {
|
||||
if e.initialized {
|
||||
return errors.New("LocationEngine already initialized")
|
||||
}
|
||||
@ -108,7 +110,7 @@ func (e *LocationEngine) AddPrefixPriority(path string, handler fasthttp.Request
|
||||
return err
|
||||
}
|
||||
|
||||
return e.prefixPriorityTree.Insert(path, handler, 2, "prefix_priority")
|
||||
return e.prefixPriorityTree.Insert(path, handler, 2, "prefix_priority", internal)
|
||||
}
|
||||
|
||||
// AddRegex 添加正则匹配 location。
|
||||
@ -117,15 +119,16 @@ func (e *LocationEngine) AddPrefixPriority(path string, handler fasthttp.Request
|
||||
// - pattern: 正则表达式模式
|
||||
// - handler: 请求处理器
|
||||
// - caseInsensitive: 是否大小写不敏感(~* 模式)
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 引擎已初始化或正则表达式无效时返回错误
|
||||
func (e *LocationEngine) AddRegex(pattern string, handler fasthttp.RequestHandler, caseInsensitive bool) error {
|
||||
func (e *LocationEngine) AddRegex(pattern string, handler fasthttp.RequestHandler, caseInsensitive bool, internal bool) error {
|
||||
if e.initialized {
|
||||
return errors.New("LocationEngine already initialized")
|
||||
}
|
||||
|
||||
matcher, err := NewRegexMatcher(pattern, handler, 3, caseInsensitive)
|
||||
matcher, err := NewRegexMatcher(pattern, handler, 3, caseInsensitive, internal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid regex pattern: %w", err)
|
||||
}
|
||||
@ -139,10 +142,11 @@ func (e *LocationEngine) AddRegex(pattern string, handler fasthttp.RequestHandle
|
||||
// 参数:
|
||||
// - path: 前缀路径
|
||||
// - handler: 请求处理器
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 引擎已初始化或路径冲突时返回错误
|
||||
func (e *LocationEngine) AddPrefix(path string, handler fasthttp.RequestHandler) error {
|
||||
func (e *LocationEngine) AddPrefix(path string, handler fasthttp.RequestHandler, internal bool) error {
|
||||
if e.initialized {
|
||||
return errors.New("LocationEngine already initialized")
|
||||
}
|
||||
@ -151,7 +155,7 @@ func (e *LocationEngine) AddPrefix(path string, handler fasthttp.RequestHandler)
|
||||
return err
|
||||
}
|
||||
|
||||
return e.prefixTree.Insert(path, handler, 4, "prefix")
|
||||
return e.prefixTree.Insert(path, handler, 4, "prefix", internal)
|
||||
}
|
||||
|
||||
// AddNamed 添加命名 location。
|
||||
|
||||
@ -42,6 +42,9 @@ type MatchResult struct {
|
||||
// Handler 匹配到的请求处理器
|
||||
Handler fasthttp.RequestHandler
|
||||
|
||||
// Internal 是否为 internal location
|
||||
Internal bool
|
||||
|
||||
// LocationType 匹配类型(exact/prefix/regex 等)
|
||||
LocationType string
|
||||
|
||||
|
||||
@ -35,11 +35,12 @@ func NewPrefixMatcher() *PrefixMatcher {
|
||||
// 参数:
|
||||
// - path: 前缀路径
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 路径重复或树已初始化时返回错误
|
||||
func (pm *PrefixMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
||||
return pm.tree.Insert(path, handler, pm.priority, "prefix")
|
||||
func (pm *PrefixMatcher) AddPath(path string, handler fasthttp.RequestHandler, internal bool) error {
|
||||
return pm.tree.Insert(path, handler, pm.priority, "prefix", internal)
|
||||
}
|
||||
|
||||
// Match 前缀匹配,返回最长前缀匹配结果。
|
||||
|
||||
@ -35,11 +35,12 @@ func NewPrefixPriorityMatcher() *PrefixPriorityMatcher {
|
||||
// 参数:
|
||||
// - path: 前缀优先路径
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 路径重复或树已初始化时返回错误
|
||||
func (ppm *PrefixPriorityMatcher) AddPath(path string, handler fasthttp.RequestHandler) error {
|
||||
return ppm.tree.Insert(path, handler, ppm.priority, "prefix_priority")
|
||||
func (ppm *PrefixPriorityMatcher) AddPath(path string, handler fasthttp.RequestHandler, internal bool) error {
|
||||
return ppm.tree.Insert(path, handler, ppm.priority, "prefix_priority", internal)
|
||||
}
|
||||
|
||||
// Match 前缀优先匹配,返回最长前缀匹配结果。
|
||||
|
||||
@ -29,6 +29,9 @@ type RadixNode struct {
|
||||
// priority 匹配优先级
|
||||
priority int
|
||||
|
||||
// internal 是否为 internal location
|
||||
internal bool
|
||||
|
||||
// isLeaf 是否为叶子节点(有 handler)
|
||||
isLeaf bool
|
||||
|
||||
@ -70,14 +73,15 @@ func NewRadixTree() *RadixTree {
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - priority: 匹配优先级
|
||||
// - locationType: 位置类型标识
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 树已初始化或路径已存在时返回错误
|
||||
func (t *RadixTree) Insert(path string, handler fasthttp.RequestHandler, priority int, locationType string) error {
|
||||
func (t *RadixTree) Insert(path string, handler fasthttp.RequestHandler, priority int, locationType string, internal bool) error {
|
||||
if t.initialized {
|
||||
return errors.New("RadixTree already initialized")
|
||||
}
|
||||
return t.insertNode(nil, t.root, path, handler, priority, locationType)
|
||||
return t.insertNode(nil, t.root, path, handler, priority, locationType, internal)
|
||||
}
|
||||
|
||||
// insertNode 完整路径分割插入算法。
|
||||
@ -95,10 +99,11 @@ func (t *RadixTree) Insert(path string, handler fasthttp.RequestHandler, priorit
|
||||
// - handler: 请求处理器
|
||||
// - priority: 优先级
|
||||
// - locationType: 位置类型
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 路径已存在时返回错误
|
||||
func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string, handler fasthttp.RequestHandler, priority int, locationType string) error {
|
||||
func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string, handler fasthttp.RequestHandler, priority int, locationType string, internal bool) error {
|
||||
// Case 1: 空节点(根节点),直接设置
|
||||
if node.prefix == "" && len(node.children) == 0 && node.handler == nil {
|
||||
if path == "" {
|
||||
@ -106,6 +111,7 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
||||
node.priority = priority
|
||||
node.isLeaf = true
|
||||
node.locationType = locationType
|
||||
node.internal = internal
|
||||
return nil
|
||||
}
|
||||
// 创建新子节点
|
||||
@ -115,6 +121,7 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
||||
isLeaf: true,
|
||||
priority: priority,
|
||||
locationType: locationType,
|
||||
internal: internal,
|
||||
}
|
||||
node.children = append(node.children, newNode)
|
||||
return nil
|
||||
@ -140,13 +147,14 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
||||
node.priority = priority
|
||||
node.isLeaf = true
|
||||
node.locationType = locationType
|
||||
node.internal = internal
|
||||
return nil
|
||||
}
|
||||
|
||||
// 搜索匹配剩余路径的子节点
|
||||
for _, child := range node.children {
|
||||
if strings.HasPrefix(remaining, child.prefix) {
|
||||
return t.insertNode(node, child, remaining, handler, priority, locationType)
|
||||
return t.insertNode(node, child, remaining, handler, priority, locationType, internal)
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +165,7 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
||||
isLeaf: true,
|
||||
priority: priority,
|
||||
locationType: locationType,
|
||||
internal: internal,
|
||||
}
|
||||
node.children = append(node.children, newNode)
|
||||
return nil
|
||||
@ -179,6 +188,7 @@ func (t *RadixTree) insertNode(parent *RadixNode, node *RadixNode, path string,
|
||||
isLeaf: true,
|
||||
priority: priority,
|
||||
locationType: locationType,
|
||||
internal: internal,
|
||||
}
|
||||
|
||||
// 将原节点和新节点作为 splitNode 的子节点
|
||||
@ -243,6 +253,7 @@ func (t *RadixTree) searchLongest(node *RadixNode, path string, bestMatch *Match
|
||||
Path: node.prefix,
|
||||
Priority: node.priority,
|
||||
LocationType: node.locationType,
|
||||
Internal: node.internal,
|
||||
}
|
||||
|
||||
// nil-safe 优先级比较 + 长度比较
|
||||
|
||||
@ -28,6 +28,9 @@ type RegexMatcher struct {
|
||||
// priority 匹配优先级,正则匹配为 3
|
||||
priority int
|
||||
|
||||
// internal 是否为 internal location
|
||||
internal bool
|
||||
|
||||
// caseInsensitive 是否大小写不敏感(~* 模式)
|
||||
caseInsensitive bool
|
||||
}
|
||||
@ -39,11 +42,12 @@ type RegexMatcher struct {
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - priority: 优先级(通常设为 3)
|
||||
// - caseInsensitive: 是否大小写不敏感
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - *RegexMatcher: 正则匹配器实例
|
||||
// - error: 正则表达式编译失败时返回错误
|
||||
func NewRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority int, caseInsensitive bool) (*RegexMatcher, error) {
|
||||
func NewRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority int, caseInsensitive bool, internal bool) (*RegexMatcher, error) {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -54,6 +58,7 @@ func NewRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority i
|
||||
handler: handler,
|
||||
priority: priority,
|
||||
caseInsensitive: caseInsensitive,
|
||||
internal: internal,
|
||||
captures: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
@ -67,11 +72,12 @@ func NewRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority i
|
||||
// - handler: 匹配成功后的请求处理器
|
||||
// - priority: 优先级
|
||||
// - caseInsensitive: 是否大小写不敏感
|
||||
// - internal: 是否为 internal location
|
||||
//
|
||||
// 返回值:
|
||||
// - *RegexMatcher: 正则匹配器实例
|
||||
func MustRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority int, caseInsensitive bool) *RegexMatcher {
|
||||
m, err := NewRegexMatcher(pattern, handler, priority, caseInsensitive)
|
||||
func MustRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority int, caseInsensitive bool, internal bool) *RegexMatcher {
|
||||
m, err := NewRegexMatcher(pattern, handler, priority, caseInsensitive, internal)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -104,6 +110,7 @@ func (m *RegexMatcher) Result() *MatchResult {
|
||||
Priority: m.priority,
|
||||
LocationType: locType,
|
||||
Captures: m.captures,
|
||||
Internal: m.internal,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user