This is an automated email from the ASF dual-hosted git repository.

ztelur pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new eebb7f0  using trie enhance dubbo route.go (#310)
eebb7f0 is described below

commit eebb7f002a041d1418adb13c045d06a61e4df142
Author: yqxu <[email protected]>
AuthorDate: Sun Dec 19 14:29:28 2021 +0800

    using trie enhance dubbo route.go (#310)
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    * using trie enhance dubbo route.go
    
    Co-authored-by: Xin.Zh <[email protected]>
    Co-authored-by: randy <[email protected]>
---
 pkg/common/constant/http.go                        |   1 +
 pkg/common/router/trie/trie.go                     |  15 +-
 pkg/common/router/trie/trie_test.go                |  69 ++++++++
 pkg/common/util/stringutil/stringutil.go           |   7 +-
 pkg/filter/http/apiconfig/api/discovery_service.go |   8 +
 .../http/apiconfig/api/discovery_service_test.go   |   5 +-
 pkg/filter/http/apiconfig/api_config.go            |  10 +-
 pkg/router/route.go                                | 187 ++++++++++-----------
 pkg/router/route_test.go                           | 136 +++++++--------
 9 files changed, 255 insertions(+), 183 deletions(-)

diff --git a/pkg/common/constant/http.go b/pkg/common/constant/http.go
index 0a488bc..b8e01c8 100644
--- a/pkg/common/constant/http.go
+++ b/pkg/common/constant/http.go
@@ -31,6 +31,7 @@ const (
        HeaderValueAll       = "*"
 
        PathSlash           = "/"
+       ProtocolSlash       = "://"
        PathParamIdentifier = ":"
 )
 
diff --git a/pkg/common/router/trie/trie.go b/pkg/common/router/trie/trie.go
index d34b84d..f53db34 100644
--- a/pkg/common/router/trie/trie.go
+++ b/pkg/common/router/trie/trie.go
@@ -18,12 +18,13 @@
 package trie
 
 import (
-       "github.com/pkg/errors"
+       "strings"
 )
 
 import (
        "github.com/apache/dubbo-go-pixiu/pkg/common/util/stringutil"
        "github.com/apache/dubbo-go-pixiu/pkg/logger"
+       "github.com/pkg/errors"
 )
 
 // Trie
@@ -54,6 +55,10 @@ type Node struct {
        bizInfo          interface{}      // route info and any other info 
store here.
 }
 
+func (trie *Trie) Clear() bool {
+       return trie.root.Clear()
+}
+
 //IsEmpty put key and values into trie as map.
 func (trie *Trie) IsEmpty() bool {
        return trie.root.IsEmpty()
@@ -103,6 +108,7 @@ func (trie Trie) Get(withOutHost string) (*Node, []string, 
bool, error) {
 //bool is ok
 //error
 func (trie Trie) Match(withOutHost string) (*Node, []string, bool) {
+       withOutHost = strings.Split(withOutHost, "?")[0]
        parts := stringutil.Split(withOutHost)
        node, param, ok := trie.root.Match(parts)
        length := len(param)
@@ -166,6 +172,11 @@ func (node *Node) internalPut(keys []string, bizInfo 
interface{}) (bool, error)
 
 }
 
+func (node *Node) Clear() bool {
+       *node = Node{}
+       return true
+}
+
 //IsEmpty return true if empty
 func (node *Node) IsEmpty() bool {
        if node.children == nil && node.matchStr == "" && node.PathVariableNode 
== nil && node.PathVariablesSet == nil {
@@ -320,7 +331,7 @@ func (node *Node) putNode(matchStr string, isReal bool, 
bizInfo interface{}) boo
        if isReal {
                selfNode.bizInfo = bizInfo
        }
-       selfNode.endOfPath = selfNode.endOfPath || old.endOfPath
+       selfNode.endOfPath = isReal || old.endOfPath
        node.children[matchStr] = selfNode
        return true
 }
diff --git a/pkg/common/router/trie/trie_test.go 
b/pkg/common/router/trie/trie_test.go
index ee53f11..4d5ea53 100644
--- a/pkg/common/router/trie/trie_test.go
+++ b/pkg/common/router/trie/trie_test.go
@@ -22,6 +22,7 @@ import (
 )
 
 import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/util/stringutil"
        "github.com/stretchr/testify/assert"
 )
 
@@ -71,6 +72,9 @@ func TestTrie_MatchAndGet(t *testing.T) {
        result, _, _ := trie.Match("/a/b")
        assert.Equal(t, result.GetBizInfo(), "ab")
 
+       result, _, _ = trie.Match("/a/b?a=b&c=d")
+       assert.Equal(t, result.GetBizInfo(), "ab")
+
        _, _ = trie.Put("POST/api/v1/**", "ab")
        result, _, _ = trie.Match("POST/api/v1")
        assert.Equal(t, "ab", result.GetBizInfo())
@@ -133,4 +137,69 @@ func TestTrie_MatchAndGet(t *testing.T) {
        node, _, ok, _ = trie.Get("/path1/:p/path2/:p2")
        assert.True(t, ok)
        assert.True(t, node.GetBizInfo() == "test1")
+
+       node, _, ok = trie.Match("/path1/12/path2/12?a=b")
+       assert.True(t, ok)
+       assert.True(t, node.GetBizInfo() == "test1")
+}
+
+func TestTrie_Clear(t *testing.T) {
+       v := "http://baidu.com/aa/bb";
+       v = stringutil.GetTrieKey("PUT", v)
+       assert.Equal(t, "PUT/aa/bb", v)
+
+       trie := NewTrie()
+       ret, _ := trie.Put("/path1/:pathvarible1/path2/:pathvarible2", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path1/:pathvarible1/path2/:pathvarible2/**", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path2/:pathvarible1/path2/:pathvarible2", "")
+       assert.True(t, ret)
+       ret, _ = trie.Put("/path2/3/path2/:pathvarible2", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path2/3/path2/:pathvarible2", "")
+       assert.False(t, ret)
+
+       ret, _ = trie.Put("/path2/3/path2/:pathvarible2/3", "")
+       assert.True(t, ret)
+       ret, _ = trie.Put("/path2/3/path2/:432423/3", "")
+       assert.False(t, ret)
+       ret, _ = trie.Put("/path2/3/path2/:432423/3/a/b/c/d/:fdsa", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path2/3/path2/:432423/3/a/b/c/c/:fdsa", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path2/3/path2/:432423/3/a/b/c/c/:fdsafdsafsdafsda", 
"")
+       assert.False(t, ret)
+
+       ret, _ = trie.Put("/path1/:pathvarible1/path2/:pathvarible2/:fdsa", "")
+       assert.True(t, ret)
+
+       ret, _ = trie.Put("/path1/:432/path2/:34", "")
+
+       assert.False(t, ret)
+       assert.False(t, trie.IsEmpty())
+       trie.Clear()
+       assert.True(t, trie.IsEmpty())
+}
+
+func TestTrie_ParamMatch(t *testing.T) {
+       trie := NewTrie()
+       ret, _ := trie.Put("PUT/path1/:pathvarible1/path2/:pathvarible2", "")
+       assert.True(t, ret)
+       str := "https://www.baidu.com/path1/param1/path2/param2?aaaaa=aaaaa";
+
+       node, _, ok := trie.Match(stringutil.GetTrieKey("PUT", str))
+       assert.True(t, ok)
+       assert.Equal(t, "", node.GetBizInfo())
+
+       ret, _ = trie.Put("PUT/path1/:pathvarible1/path2", "")
+       node, _, ok = trie.Match(stringutil.GetTrieKey("PUT", str))
+       assert.True(t, ok)
+       assert.Equal(t, "", node.GetBizInfo())
+       assert.True(t, ret)
 }
diff --git a/pkg/common/util/stringutil/stringutil.go 
b/pkg/common/util/stringutil/stringutil.go
index 355365f..6b0c9ce 100644
--- a/pkg/common/util/stringutil/stringutil.go
+++ b/pkg/common/util/stringutil/stringutil.go
@@ -72,14 +72,19 @@ func IsMatchAll(key string) bool {
 
 func GetTrieKey(method string, path string) string {
        ret := ""
+       //"http://localhost:8882/api/v1/test-dubbo/user?name=tc";
+       if strings.Contains(path, constant.ProtocolSlash) {
+               path = path[strings.Index(path, 
constant.ProtocolSlash)+len(constant.ProtocolSlash):]
+               path = path[strings.Index(path, constant.PathSlash)+1:]
+       }
        if strings.HasPrefix(path, constant.PathSlash) {
                ret = method + path
        } else {
                ret = method + constant.PathSlash + path
        }
-
        if strings.HasSuffix(ret, constant.PathSlash) {
                ret = ret[0 : len(ret)-1]
        }
+       ret = strings.Split(ret, "?")[0]
        return ret
 }
diff --git a/pkg/filter/http/apiconfig/api/discovery_service.go 
b/pkg/filter/http/apiconfig/api/discovery_service.go
index 818666e..f7f1765 100644
--- a/pkg/filter/http/apiconfig/api/discovery_service.go
+++ b/pkg/filter/http/apiconfig/api/discovery_service.go
@@ -41,6 +41,7 @@ type APIDiscoveryService interface {
        AddAPI(fr.API) error
        ClearAPI() error
        GetAPI(string, config.HTTPVerb) (fr.API, error)
+       MatchAPI(string, config.HTTPVerb) (fr.API, error)
        RemoveAPIByPath(deleted config.Resource) error
        RemoveAPIByIntance(api fr.API) error
        RemoveAPI(fullPath string, method config.Method) error
@@ -72,6 +73,13 @@ func (l *LocalMemoryAPIDiscoveryService) GetAPI(url string, 
httpVerb config.HTTP
        return fr.API{}, errors.New("not found")
 }
 
+func (l *LocalMemoryAPIDiscoveryService) MatchAPI(url string, httpVerb 
config.HTTPVerb) (fr.API, error) {
+       if api, ok := l.router.MatchAPI(url, httpVerb); ok {
+               return *api, nil
+       }
+       return fr.API{}, errors.New("not found")
+}
+
 // ClearAPI clear all api
 func (l *LocalMemoryAPIDiscoveryService) ClearAPI() error {
        return l.router.ClearAPI()
diff --git a/pkg/filter/http/apiconfig/api/discovery_service_test.go 
b/pkg/filter/http/apiconfig/api/discovery_service_test.go
index a782c40..d12dda8 100644
--- a/pkg/filter/http/apiconfig/api/discovery_service_test.go
+++ b/pkg/filter/http/apiconfig/api/discovery_service_test.go
@@ -18,6 +18,7 @@
 package api
 
 import (
+       "strings"
        "testing"
 )
 
@@ -128,7 +129,7 @@ func TestLoadAPIFromResource(t *testing.T) {
        assert.Equal(t, rsp.URLPattern, "/")
        rsp, _ = apiDiscSrv.GetAPI("/mock", fc.MethodGet)
        assert.Equal(t, rsp.URLPattern, "/mock")
-       rsp, _ = apiDiscSrv.GetAPI("/mock2/12345", fc.MethodPut)
+       rsp, _ = apiDiscSrv.MatchAPI("/mock2/12345", fc.MethodPut)
        assert.Equal(t, rsp.URLPattern, "/mock2/:id")
 
        tempResources = []fc.Resource{
@@ -181,5 +182,5 @@ func TestLoadAPIFromMethods(t *testing.T) {
        assert.Equal(t, rsp.URLPattern, "/mock")
        rsp, _ = apiDiscSrv.GetAPI("/mock", fc.MethodGet)
        assert.Equal(t, rsp.URLPattern, "/mock")
-       assert.EqualError(t, err, "path: /mock, Method: PUT, error: Method PUT 
with address localhost:8080 already exists in path /mock")
+       assert.True(t, strings.Contains(err.Error(), "path: /mock, Method: PUT, 
error: Method PUT with address /mock already exists in path /mock"))
 }
diff --git a/pkg/filter/http/apiconfig/api_config.go 
b/pkg/filter/http/apiconfig/api_config.go
index 2917077..50518a0 100644
--- a/pkg/filter/http/apiconfig/api_config.go
+++ b/pkg/filter/http/apiconfig/api_config.go
@@ -82,11 +82,11 @@ func (f *Filter) Apply() error {
                return nil
        }
 
-       config, err := initApiConfig(f.cfg)
+       cfg, err := initApiConfig(f.cfg)
        if err != nil {
                logger.Errorf("Get ApiConfig fail: %v", err)
        }
-       if err := f.apiService.InitAPIsFromConfig(*config); err != nil {
+       if err := f.apiService.InitAPIsFromConfig(*cfg); err != nil {
                logger.Errorf("InitAPIsFromConfig fail: %v", err)
        }
 
@@ -115,7 +115,7 @@ func (f *Filter) PrepareFilterChain(ctx 
*contexthttp.HttpContext) error {
 
 func (f *Filter) Handle(ctx *contexthttp.HttpContext) {
        req := ctx.Request
-       api, err := f.apiService.GetAPI(req.URL.Path, fc.HTTPVerb(req.Method))
+       v, err := f.apiService.MatchAPI(req.URL.Path, fc.HTTPVerb(req.Method))
        if err != nil {
                if _, err := ctx.WriteWithStatus(http.StatusNotFound, 
constant.Default404Body); err != nil {
                        logger.Errorf("WriteWithStatus fail: %v", err)
@@ -127,7 +127,7 @@ func (f *Filter) Handle(ctx *contexthttp.HttpContext) {
                return
        }
 
-       if !api.Method.Enable {
+       if !v.Method.Enable {
                if _, err := ctx.WriteWithStatus(http.StatusNotAcceptable, 
constant.Default406Body); err != nil {
                        logger.Errorf("WriteWithStatus fail: %v", err)
                }
@@ -138,7 +138,7 @@ func (f *Filter) Handle(ctx *contexthttp.HttpContext) {
                ctx.Abort()
                return
        }
-       ctx.API(api)
+       ctx.API(v)
        ctx.Next()
 }
 
diff --git a/pkg/router/route.go b/pkg/router/route.go
index 559524f..6961b03 100644
--- a/pkg/router/route.go
+++ b/pkg/router/route.go
@@ -26,131 +26,103 @@ import (
 import (
        "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/api/config"
        "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/router"
-
-       "github.com/emirpasic/gods/trees/avltree"
-
        "github.com/pkg/errors"
 )
 
 import (
        "github.com/apache/dubbo-go-pixiu/pkg/common/constant"
+       "github.com/apache/dubbo-go-pixiu/pkg/common/router/trie"
+       "github.com/apache/dubbo-go-pixiu/pkg/common/util/stringutil"
 )
 
 // Node defines the single method of the router configured API
 type Node struct {
        fullPath string
-       wildcard bool
        filters  []string
-       methods  map[config.HTTPVerb]*config.Method
+       method   *config.Method
        headers  map[string]string
 }
 
 // Route defines the tree of router APIs
 type Route struct {
-       lock         sync.RWMutex
-       tree         *avltree.Tree
-       wildcardTree *avltree.Tree
+       lock sync.RWMutex
+       tree trie.Trie
 }
 
 // ClearAPI clear the api
 func (rt *Route) ClearAPI() error {
        rt.lock.Lock()
        defer rt.lock.Unlock()
-       rt.wildcardTree.Clear()
        rt.tree.Clear()
        return nil
 }
 
 func (r *Route) RemoveAPI(api router.API) {
-       fullPath := api.URLPattern
-       node, ok := r.findNode(fullPath)
-       if !ok {
-               return
-       }
-       if tempMethod, ok := node.methods[api.HTTPVerb]; ok {
-               splitedURLs := 
strings.Split(tempMethod.IntegrationRequest.HTTPBackendConfig.URL, ",")
-               afterRemoveedURL := make([]string, 0, len(splitedURLs))
-               for _, v := range splitedURLs {
-                       if v != api.IntegrationRequest.HTTPBackendConfig.URL {
-                               afterRemoveedURL = append(afterRemoveedURL, v)
-                       }
-               }
-               if len(afterRemoveedURL) == 0 {
-                       delete(node.methods, api.HTTPVerb)
+       r.lock.Lock()
+       defer r.lock.Unlock()
+       lowerCasePath := strings.ToLower(api.URLPattern)
+       key := getTrieKey(api.Method.HTTPVerb, lowerCasePath, false)
+       _, _ = r.tree.Remove(key)
+}
+
+func getTrieKey(method config.HTTPVerb, path string, isPrefix bool) string {
+       if isPrefix {
+               if !strings.HasSuffix(path, constant.PathSlash) {
+                       path = path + constant.PathSlash
                }
-               
node.methods[api.HTTPVerb].IntegrationRequest.HTTPBackendConfig.URL = 
strings.Join(afterRemoveedURL, ",")
-               return
+               path = path + "**"
        }
+       return stringutil.GetTrieKey(string(method), path)
 }
 
 // PutAPI puts an api into the resource
 func (rt *Route) PutAPI(api router.API) error {
-       fullPath := api.URLPattern
-       node, ok := rt.findNode(fullPath)
-       rt.lock.Lock()
-       defer rt.lock.Unlock()
+       lowerCasePath := strings.ToLower(api.URLPattern)
+       key := getTrieKey(api.Method.HTTPVerb, lowerCasePath, false)
+       node, ok := rt.getNode(key)
        if !ok {
-               wildcard := strings.Contains(fullPath, 
constant.PathParamIdentifier)
                rn := &Node{
-                       fullPath: fullPath,
-                       methods:  
map[config.HTTPVerb]*config.Method{api.Method.HTTPVerb: &api.Method},
-                       wildcard: wildcard,
+                       fullPath: lowerCasePath,
+                       method:   &api.Method,
                        headers:  api.Headers,
                }
-               if wildcard {
-                       rt.wildcardTree.Put(fullPath, rn)
-               }
-               rt.tree.Put(fullPath, rn)
+               rt.lock.Lock()
+               defer rt.lock.Unlock()
+               _, _ = rt.tree.Put(key, rn)
                return nil
        }
-       return node.putMethod(api.Method, api.Headers)
+       return errors.Errorf("Method %s with address %s already exists in path 
%s",
+               api.Method.HTTPVerb, lowerCasePath, node.fullPath)
 }
 
-func (node *Node) putMethod(method config.Method, headers map[string]string) 
error {
-       // todo lock
-       if tempMethod, ok := node.methods[method.HTTPVerb]; ok {
-               splitedURLs := 
strings.Split(tempMethod.IntegrationRequest.HTTPBackendConfig.URL, ",")
-               for _, v := range splitedURLs {
-                       if v == method.IntegrationRequest.HTTPBackendConfig.URL 
{
-                               return errors.Errorf("Method %s with address %s 
already exists in path %s",
-                                       method.HTTPVerb, v, node.fullPath)
-                       }
-               }
-               splitedURLs = append(splitedURLs, 
method.IntegrationRequest.HTTPBackendConfig.URL)
-               
node.methods[method.HTTPVerb].IntegrationRequest.HTTPBackendConfig.URL = 
strings.Join(splitedURLs, ",")
-               node.headers = headers
-               return nil
-       }
-       node.methods[method.HTTPVerb] = &method
-       node.headers = headers
-       return nil
-}
-
-// UpdateAPI update the api method in the existing router node
-func (rt *Route) UpdateAPI(api router.API) error {
-       node, found := rt.findNode(api.URLPattern)
-       if found {
-               if _, ok := node.methods[api.Method.HTTPVerb]; ok {
-                       rt.lock.Lock()
-                       defer rt.lock.Unlock()
-                       node.methods[api.Method.HTTPVerb] = &api.Method
-               }
+// FindAPI return if api has path in trie,or nil
+func (rt *Route) FindAPI(fullPath string, httpverb config.HTTPVerb) 
(*router.API, bool) {
+       lowerCasePath := strings.ToLower(fullPath)
+       key := getTrieKey(httpverb, lowerCasePath, false)
+       if n, found := rt.getNode(key); found {
+               rt.lock.RLock()
+               defer rt.lock.RUnlock()
+               return &router.API{
+                       URLPattern: n.fullPath,
+                       Method:     *n.method,
+                       Headers:    n.headers,
+               }, found
        }
-       return nil
+       return nil, false
 }
 
-// FindAPI returns the api that meets the
-func (rt *Route) FindAPI(fullPath string, httpverb config.HTTPVerb) 
(*router.API, bool) {
-       if n, found := rt.findNode(fullPath); found {
+// MatchAPI FindAPI returns the api that meets the rule
+func (rt *Route) MatchAPI(fullPath string, httpverb config.HTTPVerb) 
(*router.API, bool) {
+       lowerCasePath := strings.ToLower(fullPath)
+       key := getTrieKey(httpverb, lowerCasePath, false)
+       if n, found := rt.matchNode(key); found {
                rt.lock.RLock()
                defer rt.lock.RUnlock()
-               if method, ok := n.methods[httpverb]; ok {
-                       return &router.API{
-                               URLPattern: n.fullPath,
-                               Method:     *method,
-                               Headers:    n.headers,
-                       }, ok
-               }
+               return &router.API{
+                       URLPattern: n.fullPath,
+                       Method:     *n.method,
+                       Headers:    n.headers,
+               }, found
        }
        return nil, false
 }
@@ -159,51 +131,63 @@ func (rt *Route) FindAPI(fullPath string, httpverb 
config.HTTPVerb) (*router.API
 func (rt *Route) DeleteNode(fullPath string) bool {
        rt.lock.RLock()
        defer rt.lock.RUnlock()
-       rt.tree.Remove(fullPath)
+       methodList := [8]config.HTTPVerb{"ANY", "GET", "HEAD", "POST", "PUT", 
"PATCH", "DELETE", "OPTIONS"}
+       for _, v := range methodList {
+               key := getTrieKey(v, fullPath, false)
+               _, _ = rt.tree.Remove(key)
+       }
        return true
 }
 
 // DeleteAPI delete api by fullPath and http verb
 func (rt *Route) DeleteAPI(fullPath string, httpverb config.HTTPVerb) bool {
-       if n, found := rt.findNode(fullPath); found {
+       lowerCasePath := strings.ToLower(fullPath)
+       key := getTrieKey(httpverb, lowerCasePath, false)
+       if _, found := rt.getNode(key); found {
                rt.lock.RLock()
                defer rt.lock.RUnlock()
-               delete(n.methods, httpverb)
+               _, _ = rt.tree.Remove(key)
                return true
        }
        return false
 }
 
-func (rt *Route) findNode(fullPath string) (*Node, bool) {
+func (rt *Route) getNode(fullPath string) (*Node, bool) {
        var n interface{}
        var found bool
-       if n, found = rt.searchWildcard(fullPath); !found {
-               rt.lock.RLock()
-               defer rt.lock.RUnlock()
-               if n, found = rt.tree.Get(fullPath); !found {
-                       return nil, false
-               }
+       rt.lock.RLock()
+       defer rt.lock.RUnlock()
+       trieNode, _, _, _ := rt.tree.Get(fullPath)
+       found = trieNode != nil
+       if !found {
+               return nil, false
+       }
+       n = trieNode.GetBizInfo()
+       if n == nil {
+               return nil, false
        }
        return n.(*Node), found
 }
 
-func (rt *Route) searchWildcard(fullPath string) (*Node, bool) {
+func (rt *Route) matchNode(fullPath string) (*Node, bool) {
+       var n interface{}
+       var found bool
        rt.lock.RLock()
        defer rt.lock.RUnlock()
-       wildcardPaths := rt.wildcardTree.Keys()
-       for _, p := range wildcardPaths {
-               if wildcardMatch(p.(string), fullPath) != nil {
-                       n, ok := rt.wildcardTree.Get(p)
-                       return n.(*Node), ok
-               }
+       trieNode, _, _ := rt.tree.Match(fullPath)
+       found = trieNode != nil
+       if !found {
+               return nil, false
        }
-       return nil, false
+       n = trieNode.GetBizInfo()
+       if n == nil {
+               return nil, false
+       }
+       return n.(*Node), found
 }
 
-// wildcardMatch validate if the checkPath meets the wildcardPath,
-// for example /vought/12345 should match wildcard path /vought/:id;
-// /vought/1234abcd/status should not match /vought/:id;
 func wildcardMatch(wildcardPath string, checkPath string) url.Values {
+
        cPaths := strings.Split(strings.TrimLeft(checkPath, 
constant.PathSlash), constant.PathSlash)
        wPaths := strings.Split(strings.TrimLeft(wildcardPath, 
constant.PathSlash), constant.PathSlash)
        result := url.Values{}
@@ -224,7 +208,6 @@ func wildcardMatch(wildcardPath string, checkPath string) 
url.Values {
 // NewRoute returns an empty router tree
 func NewRoute() *Route {
        return &Route{
-               tree:         avltree.NewWithStringComparator(),
-               wildcardTree: avltree.NewWithStringComparator(),
+               tree: trie.NewTrie(),
        }
 }
diff --git a/pkg/router/route_test.go b/pkg/router/route_test.go
index 7275b14..d4e3bca 100644
--- a/pkg/router/route_test.go
+++ b/pkg/router/route_test.go
@@ -20,13 +20,10 @@ package router
 import (
        "testing"
 )
-
 import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/router/trie"
        "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/api/config"
        "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/router"
-
-       "github.com/emirpasic/gods/trees/avltree"
-
        "github.com/stretchr/testify/assert"
 )
 
@@ -43,12 +40,11 @@ func getMockMethod(verb config.HTTPVerb) config.Method {
 
 func TestPut(t *testing.T) {
        rt := &Route{
-               tree:         avltree.NewWithStringComparator(),
-               wildcardTree: avltree.NewWithStringComparator(),
+               tree: trie.NewTrie(),
        }
        n0 := getMockMethod(config.MethodGet)
-       rt.PutAPI(router.API{URLPattern: "/", Method: n0})
-       _, ok := rt.tree.Get("/")
+       _ = rt.PutAPI(router.API{URLPattern: "/", Method: n0})
+       _, ok := rt.FindAPI("/", n0.HTTPVerb)
        assert.True(t, ok)
 
        err := rt.PutAPI(router.API{URLPattern: "/", Method: n0})
@@ -59,36 +55,33 @@ func TestPut(t *testing.T) {
        assert.Nil(t, err)
        err = rt.PutAPI(router.API{URLPattern: "/mock", Method: n1})
        assert.Nil(t, err)
-       mNode, ok := rt.tree.Get("/mock")
+       _, ok = rt.FindAPI("/mock", n0.HTTPVerb)
+       assert.True(t, ok)
+       _, ok = rt.FindAPI("/mock", n1.HTTPVerb)
        assert.True(t, ok)
-       assert.Equal(t, len(mNode.(*Node).methods), 2)
 
        err = rt.PutAPI(router.API{URLPattern: "/mock/test", Method: n0})
        assert.Nil(t, err)
-       _, ok = rt.tree.Get("/mock/test")
+       _, ok = rt.FindAPI("/mock/test", n0.HTTPVerb)
        assert.True(t, ok)
 
-       rt.PutAPI(router.API{URLPattern: "/test/:id", Method: n0})
-       tNode, ok := rt.tree.Get("/test/:id")
+       _ = rt.PutAPI(router.API{URLPattern: "/test/:id", Method: n0})
+       _, ok = rt.FindAPI("/test/:id", n0.HTTPVerb)
        assert.True(t, ok)
-       assert.True(t, tNode.(*Node).wildcard)
 
        err = rt.PutAPI(router.API{URLPattern: "/test/:id", Method: n1})
        assert.Nil(t, err)
        err = rt.PutAPI(router.API{URLPattern: "/test/js", Method: n0})
-       assert.Error(t, err, "/test/:id wildcard already exist so that cannot 
add path /test/js")
-
+       assert.Nil(t, err)
        err = rt.PutAPI(router.API{URLPattern: "/test/:id/mock", Method: n0})
-       tNode, ok = rt.tree.Get("/test/:id/mock")
+       _, ok = rt.FindAPI("/test/:id/mock", n0.HTTPVerb)
        assert.True(t, ok)
-       assert.True(t, tNode.(*Node).wildcard)
        assert.Nil(t, err)
 }
 
-func TestFindMethod(t *testing.T) {
+func TestMatchMethod(t *testing.T) {
        rt := &Route{
-               tree:         avltree.NewWithStringComparator(),
-               wildcardTree: avltree.NewWithStringComparator(),
+               tree: trie.NewTrie(),
        }
        n0 := getMockMethod(config.MethodGet)
        n1 := getMockMethod(config.MethodPost)
@@ -99,72 +92,73 @@ func TestFindMethod(t *testing.T) {
        e = rt.PutAPI(router.API{URLPattern: "/vought/:id/supe/:name", Method: 
n1})
        assert.Nil(t, e)
 
-       m, ok := rt.FindAPI("/theboys", config.MethodGet)
+       m, ok := rt.MatchAPI("/theboys", config.MethodGet)
        assert.True(t, ok)
        assert.NotNil(t, m)
        assert.Equal(t, m.URLPattern, "/theboys")
 
-       m, ok = rt.FindAPI("/theboys", config.MethodPost)
+       m, ok = rt.MatchAPI("/theboys", config.MethodPost)
        assert.False(t, ok)
        assert.Nil(t, m)
 
-       m, ok = rt.FindAPI("/vought/123/supe/startlight", config.MethodPost)
+       m, ok = rt.MatchAPI("/vought/123/supe/startlight", config.MethodPost)
        assert.True(t, ok)
        assert.NotNil(t, m)
        assert.Equal(t, m.URLPattern, "/vought/:id/supe/:name")
 
-       m, ok = rt.FindAPI("/vought/123/supe/startlight", config.MethodPost)
+       m, ok = rt.MatchAPI("/vought/123/supe/startlight", config.MethodPost)
        assert.True(t, ok)
        assert.NotNil(t, m)
        assert.Equal(t, m.URLPattern, "/vought/:id/supe/:name")
 }
 
-func TestUpdateMethod(t *testing.T) {
-       m0 := getMockMethod(config.MethodGet)
-       m1 := getMockMethod(config.MethodGet)
-       m0.DubboBackendConfig.Version = "1.0.0"
-       m1.DubboBackendConfig.Version = "2.0.0"
-
-       rt := NewRoute()
-       rt.PutAPI(router.API{URLPattern: "/marvel", Method: m0})
-       m, _ := rt.FindAPI("/marvel", config.MethodGet)
-       assert.Equal(t, m.DubboBackendConfig.Version, "1.0.0")
-       rt.UpdateAPI(router.API{URLPattern: "/marvel", Method: m1})
-       m, ok := rt.FindAPI("/marvel", config.MethodGet)
-       assert.True(t, ok)
-       assert.Equal(t, m.DubboBackendConfig.Version, "2.0.0")
-
-       rt.PutAPI(router.API{URLPattern: "/theboys/:id", Method: m0})
-       m, _ = rt.FindAPI("/theBoys/12345", config.MethodGet)
-       assert.Equal(t, m.DubboBackendConfig.Version, "1.0.0")
-       rt.UpdateAPI(router.API{URLPattern: "/theBoys/:id", Method: m1})
-       m, ok = rt.FindAPI("/theBoys/12345", config.MethodGet)
-       assert.True(t, ok)
-       assert.Equal(t, m.DubboBackendConfig.Version, "2.0.0")
-}
-
-func TestSearchWildcard(t *testing.T) {
-       rt := &Route{
-               tree:         avltree.NewWithStringComparator(),
-               wildcardTree: avltree.NewWithStringComparator(),
-       }
-       n0 := getMockMethod(config.MethodGet)
-       e := rt.PutAPI(router.API{URLPattern: "/theboys", Method: n0})
-       assert.Nil(t, e)
-       e = rt.PutAPI(router.API{URLPattern: "/theboys/:id", Method: n0})
-       assert.Nil(t, e)
-       e = rt.PutAPI(router.API{URLPattern: "/vought/:id/supe/:name", Method: 
n0})
-       assert.Nil(t, e)
-
-       _, ok := rt.searchWildcard("/marvel")
-       assert.False(t, ok)
-       _, ok = rt.searchWildcard("/theboys/:id/age")
-       assert.False(t, ok)
-       _, ok = rt.searchWildcard("/theboys/butcher")
-       assert.True(t, ok)
-       _, ok = rt.searchWildcard("/vought/:id/supe/homelander")
-       assert.True(t, ok)
-}
+//
+//func TestUpdateMethod(t *testing.T) {
+//     m0 := getMockMethod(config.MethodGet)
+//     m1 := getMockMethod(config.MethodGet)
+//     m0.DubboBackendConfig.Version = "1.0.0"
+//     m1.DubboBackendConfig.Version = "2.0.0"
+//
+//     rt := NewRoute()
+//     rt.PutAPI(router.API{URLPattern: "/marvel", Method: m0})
+//     m, _ := rt.FindAPI("/marvel", config.MethodGet)
+//     assert.Equal(t, m.DubboBackendConfig.Version, "1.0.0")
+//     rt.UpdateAPI(router.API{URLPattern: "/marvel", Method: m1})
+//     m, ok := rt.FindAPI("/marvel", config.MethodGet)
+//     assert.True(t, ok)
+//     assert.Equal(t, m.DubboBackendConfig.Version, "2.0.0")
+//
+//     rt.PutAPI(router.API{URLPattern: "/theboys/:id", Method: m0})
+//     m, _ = rt.FindAPI("/theBoys/12345", config.MethodGet)
+//     assert.Equal(t, m.DubboBackendConfig.Version, "1.0.0")
+//     rt.UpdateAPI(router.API{URLPattern: "/theBoys/:id", Method: m1})
+//     m, ok = rt.FindAPI("/theBoys/12345", config.MethodGet)
+//     assert.True(t, ok)
+//     assert.Equal(t, m.DubboBackendConfig.Version, "2.0.0")
+//}
+
+//func TestSearchWildcard(t *testing.T) {
+//     rt := &Route{
+//             tree:         avltree.NewWithStringComparator(),
+//             wildcardTree: avltree.NewWithStringComparator(),
+//     }
+//     n0 := getMockMethod(config.MethodGet)
+//     e := rt.PutAPI(router.API{URLPattern: "/theboys", Method: n0})
+//     assert.Nil(t, e)
+//     e = rt.PutAPI(router.API{URLPattern: "/theboys/:id", Method: n0})
+//     assert.Nil(t, e)
+//     e = rt.PutAPI(router.API{URLPattern: "/vought/:id/supe/:name", Method: 
n0})
+//     assert.Nil(t, e)
+//
+//     _, ok := rt.searchWildcard("/marvel")
+//     assert.False(t, ok)
+//     _, ok = rt.searchWildcard("/theboys/:id/age")
+//     assert.False(t, ok)
+//     _, ok = rt.searchWildcard("/theboys/butcher")
+//     assert.True(t, ok)
+//     _, ok = rt.searchWildcard("/vought/:id/supe/homelander")
+//     assert.True(t, ok)
+//}
 
 func TestWildcardMatch(t *testing.T) {
        vals := wildcardMatch("/vought/:id", "/vought/12345")

Reply via email to