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