You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by zt...@apache.org on 2021/12/19 06:29:35 UTC
[dubbo-go-pixiu] branch develop updated: using trie enhance dubbo route.go (#310)
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 <31...@qq.com>
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 <dr...@foxmail.com>
Co-authored-by: randy <zt...@gmail.com>
---
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")