mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-29 17:58:36 +08:00
修正:radix match params只包含匹配的参数
This commit is contained in:
+64
-31
@@ -3,24 +3,26 @@ package appsrv
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
)
|
||||
|
||||
type RadixNode struct {
|
||||
data interface{}
|
||||
fullPath []string
|
||||
next []*RadixNode
|
||||
parent *RadixNode
|
||||
matchNext *RadixNode
|
||||
matchTable []string
|
||||
// matchTable []string
|
||||
segment string
|
||||
}
|
||||
|
||||
func NewRadix() *RadixNode {
|
||||
return &RadixNode{data: nil,
|
||||
next: make([]*RadixNode, 0),
|
||||
matchNext: nil,
|
||||
matchTable: nil,
|
||||
parent: nil,
|
||||
segment: ""}
|
||||
fullPath: nil,
|
||||
next: make([]*RadixNode, 0),
|
||||
matchNext: nil,
|
||||
parent: nil,
|
||||
segment: ""}
|
||||
}
|
||||
|
||||
func (r *RadixNode) String() string {
|
||||
@@ -50,11 +52,21 @@ func isMatchSegment(seg string) bool {
|
||||
}
|
||||
|
||||
func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
return r.add(segments, segments, data)
|
||||
}
|
||||
|
||||
func (r *RadixNode) add(path []string, segments []string, data interface{}) error {
|
||||
// log.Debugf("add %#v %#v", path, segments)
|
||||
|
||||
if len(segments) == 0 {
|
||||
if r.data != nil {
|
||||
return fmt.Errorf("Duplicate data for node %s", r.String())
|
||||
} else {
|
||||
r.data = data
|
||||
r.fullPath = make([]string, len(path))
|
||||
for i := 0; i < len(path); i += 1 {
|
||||
r.fullPath[i] = path[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -65,18 +77,18 @@ func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
return fmt.Errorf("%s has been registered, %s conflict with %s", r.matchNext.String(), r.matchNext.segment, segments[0])
|
||||
} */
|
||||
nextNode = r.matchNext
|
||||
nextNode.matchTable = append(nextNode.matchTable, segments[0])
|
||||
// nextNode.matchTable = append(nextNode.matchTable, segments[0])
|
||||
} else {
|
||||
nextNode = NewRadix()
|
||||
nextNode.segment = "<*>"
|
||||
nextNode.parent = r
|
||||
nextNode.matchTable = []string{segments[0]}
|
||||
// nextNode.matchTable = []string{segments[0]}
|
||||
r.matchNext = nextNode
|
||||
}
|
||||
} else {
|
||||
for _, node := range r.next {
|
||||
if node.segment == segments[0] {
|
||||
nextNode = node
|
||||
for i := 0; i < len(r.next); i += 1 {
|
||||
if r.next[i].segment == segments[0] {
|
||||
nextNode = r.next[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -87,42 +99,46 @@ func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
r.next = append(r.next, nextNode)
|
||||
}
|
||||
}
|
||||
return nextNode.Add(segments[1:], data)
|
||||
return nextNode.add(path, segments[1:], data)
|
||||
}
|
||||
|
||||
func (r *RadixNode) Match(segments []string, params map[string]string) interface{} {
|
||||
data, allPaths := r.match(segments)
|
||||
// log.Debugf("%#v", allPaths)
|
||||
for i := 0; i < len(segments); i += 1 {
|
||||
for j := 0; j < len(allPaths); j += 1 {
|
||||
if i < len(allPaths[j]) && isMatchSegment(allPaths[j][i]) {
|
||||
params[allPaths[j][i]] = segments[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (r *RadixNode) match(segments []string) (interface{}, [][]string) {
|
||||
if len(segments) == 0 {
|
||||
return r.data
|
||||
return r.data, r.getAllFullPaths()
|
||||
} else {
|
||||
var ret interface{} = nil
|
||||
var retData interface{} = nil
|
||||
var retPath [][]string = nil
|
||||
exactMatch := false
|
||||
for _, node := range r.next {
|
||||
if node.segment == segments[0] {
|
||||
ret = node.Match(segments[1:], params)
|
||||
if ret != nil {
|
||||
// log.Debugf("Match %s ret %#v", node.segment, ret)
|
||||
retData, retPath = node.match(segments[1:])
|
||||
if retData != nil {
|
||||
exactMatch = true
|
||||
} else {
|
||||
// log.Debugf("No match %s ret %#v", node.segment, ret)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if ret != nil {
|
||||
return ret
|
||||
if retData != nil {
|
||||
return retData, retPath
|
||||
} else {
|
||||
if !exactMatch && r.matchNext != nil {
|
||||
ret = r.matchNext.Match(segments[1:], params)
|
||||
if ret != nil {
|
||||
for _, segname := range r.matchNext.matchTable {
|
||||
if _, ok := params[segname]; !ok {
|
||||
params[segname] = segments[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
retData, retPath = r.matchNext.match(segments[1:])
|
||||
return retData, retPath
|
||||
} else {
|
||||
return r.data
|
||||
return r.data, r.getAllFullPaths()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,3 +155,20 @@ func (r *RadixNode) Walk(f func(path string, data interface{})) {
|
||||
r.matchNext.Walk(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RadixNode) getAllFullPaths() [][]string {
|
||||
if r.fullPath != nil {
|
||||
return [][]string{r.fullPath}
|
||||
}else {
|
||||
ret := make([][]string, 0)
|
||||
for _, node := range r.next {
|
||||
fp := node.getAllFullPaths()
|
||||
ret = append(ret, fp...)
|
||||
}
|
||||
if r.matchNext != nil {
|
||||
fp := r.matchNext.getAllFullPaths()
|
||||
ret = append(ret, fp...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,16 @@ func TestRadixNode(t *testing.T) {
|
||||
|
||||
func TestParams(t *testing.T) {
|
||||
r := NewRadix()
|
||||
r.Add([]string{"POST", "clouds", "<action>"}, "classAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "<action>"}, "objectAction")
|
||||
r.Add([]string{"POST", "clouds", "<cls_action>"}, "classAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "sync"}, "objectSyncAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "<obj_action>"}, "objectAction")
|
||||
params := make(map[string]string)
|
||||
ret := r.Match([]string{"POST", "clouds", "id", "sync"}, params)
|
||||
ret := r.Match([]string{"POST", "clouds", "myid", "sync"}, params)
|
||||
t.Logf("match: %s", ret)
|
||||
t.Logf("params: %s", params)
|
||||
|
||||
params = make(map[string]string)
|
||||
ret = r.Match([]string{"POST", "clouds", "myid", "start"}, params)
|
||||
t.Logf("match: %s", ret)
|
||||
t.Logf("params: %s", params)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user