router fix

This commit is contained in:
黄孟柱
2021-07-27 15:24:29 +08:00
parent 9187822122
commit cd2a15f7c6
5 changed files with 71 additions and 26 deletions

View File

@@ -12,6 +12,7 @@ import (
"fmt" "fmt"
"github.com/eolinker/goku-eosc/router/checker" "github.com/eolinker/goku-eosc/router/checker"
"sort" "sort"
"strings"
) )
type RulePath struct { type RulePath struct {
@@ -29,16 +30,16 @@ type ICreateHelper interface {
//ParseRouter parse rule to IRouter //ParseRouter parse rule to IRouter
func ParseRouter(rules []Rule,helper ICreateHelper)(IRouter,error) { func ParseRouter(rules []Rule,helper ICreateHelper)(IRouter,error) {
root:=newCreateRoot() root:=newCreateRoot(helper)
for i:=range rules{ for i:=range rules{
r:=rules[i] r:=rules[i]
err:=root.add(r.Path,NewEndpoint(r.Target,r.Path)) err:=root.add(r.Path,r.Target)
if err!= nil{ if err!= nil{
return nil,err return nil,err
} }
} }
return root.toRouter(helper ),nil return root.toRouter( ),nil
} }
type createNodes map[string]*createNode type createNodes map[string]*createNode
@@ -87,6 +88,7 @@ type createNodeList struct {
ICreateHelper ICreateHelper
} }
func (cl *createNodeList) Len() int { func (cl *createNodeList) Len() int {
return len(cl.nodes) return len(cl.nodes)
} }
@@ -99,30 +101,51 @@ func (cl *createNodeList) Swap(i, j int) {
cl.nodes[i],cl.nodes[j] = cl.nodes[j],cl.nodes[i] cl.nodes[i],cl.nodes[j] = cl.nodes[j],cl.nodes[i]
} }
type PathSort struct {
path []RulePath
helper ICreateHelper
}
func (p *PathSort) Len() int {
return len(p.path)
}
func (p *PathSort) Less(i, j int) bool {
return p.helper.Less(p.path[i].CMD,p.path[j].CMD)
}
func (p *PathSort) Swap(i, j int) {
p.path[i],p.path[j]= p.path[j],p.path[i]
}
type createRoot struct { type createRoot struct {
helper ICreateHelper
nexts createNodes nexts createNodes
} }
func newCreateRoot() *createRoot { func newCreateRoot(helper ICreateHelper) *createRoot {
return &createRoot{ return &createRoot{
nexts: make(createNodes), nexts: make(createNodes),
helper:helper,
} }
} }
func (cr *createRoot) toRouter(helper ICreateHelper) IRouter { func (cr *createRoot) toRouter() IRouter {
return cr.nexts.toRouter(helper) return cr.nexts.toRouter(cr.helper)
} }
type IEndpoint interface { type IEndPoint interface {
CMDs()[]string CMDs()[]string
Get(CMD string)(checker.Checker,bool) Get(CMD string)(checker.Checker,bool)
Target()string Target()string
EndPoint()string
} }
type tEndpoint struct { type tEndpoint struct {
target string target string
cmds []string cmds []string
checkers map[string]checker.Checker checkers map[string]checker.Checker
endpoint string
} }
func (e *tEndpoint) CMDs() []string { func (e *tEndpoint) CMDs() []string {
@@ -137,26 +160,44 @@ func (e *tEndpoint) Get(CMD string) (checker.Checker,bool) {
func (e *tEndpoint) Target() string { func (e *tEndpoint) Target() string {
return e.target return e.target
} }
func (e *tEndpoint)EndPoint()string {
return e.target
}
func NewEndpoint(target string, path []RulePath) *tEndpoint { func NewEndpoint(target string, path []RulePath) *tEndpoint {
cs:=make(map[string]checker.Checker) cs:=make(map[string]checker.Checker)
cmds:=make([]string,0,len(path)) cmds:=make([]string,0,len(path))
build:=strings.Builder{}
for _,p:=range path{ for _,p:=range path{
cs[p.CMD] = p.Checker cs[p.CMD] = p.Checker
cmds = append(cmds, p.CMD) cmds = append(cmds, p.CMD)
}
return &tEndpoint{target: target, checkers:cs,cmds:cmds} build.WriteString(p.CMD)
build.WriteString(p.Checker.Key())
build.WriteString("&")
} }
func (e *tEndpoint) Router(source ISource) (endpoint IEndpoint, has bool) { return &tEndpoint{target: target, checkers:cs,cmds:cmds,endpoint:build.String()}
}
func (e *tEndpoint) Router(source ISource) (endpoint IEndPoint, has bool) {
return e,e!= nil return e,e!= nil
} }
func (cr *createRoot) add(path []RulePath,endpoint *tEndpoint) error { func (cr *createRoot) add(path []RulePath,target string) error {
if len(path) == 0 || endpoint == nil {
if len(path) == 0 || target == "" {
return fmt.Errorf("invalid router") return fmt.Errorf("invalid router")
} }
return cr.nexts.add(path,endpoint)
cl:= &PathSort{
path:path,
helper:cr.helper,
}
sort.Sort(cl)
return cr.nexts.add(path, NewEndpoint(target,path))
} }
type createChecker struct { type createChecker struct {
@@ -193,7 +234,7 @@ func (cc *createChecker) toRouter(helper ICreateHelper) IRouter {
func (cc *createChecker) add(path []RulePath,endpoint *tEndpoint) error { func (cc *createChecker) add(path []RulePath,endpoint *tEndpoint) error {
if len(path) == 0 { if len(path) == 0 {
if cc.endpoint != nil{ if cc.endpoint != nil{
return fmt.Errorf("%s target %s: exist",cc.checker.Key(),endpoint.target) return fmt.Errorf("%s: exist",endpoint.endpoint)
} }
cc.endpoint = endpoint cc.endpoint = endpoint
return nil return nil

View File

@@ -425,13 +425,13 @@ var tests = []struct {
}, },
}, },
want: []string{"demo2", "demo3"}, want: []string{"demo2", "demo3"},
wantErr: true, wantErr: false,
}, },
} }
func TestParseRouter(t *testing.T) { func TestParseRouter(t *testing.T) {
helper := NewTestHelper([]string{"location", "header", "query"}) helper := NewTestHelper([]string{"host","location", "header", "query"})
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@@ -444,6 +444,10 @@ func TestParseRouter(t *testing.T) {
t.Errorf("ParseRouter() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("ParseRouter() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if tt.wantErr{
t.Logf("ParseRouter() error = %v ok", err)
return
}
for i, s := range tt.testCase { for i, s := range tt.testCase {
endpoint, h := r.Router(s) endpoint, h := r.Router(s)

View File

@@ -16,7 +16,7 @@ import (
) )
var _ service.IRouterEndpoint = (*EndPoint)(nil) var _ service.IRouterEndpoint = (*EndPoint)(nil)
type EndPoint struct { type EndPoint struct {
endpoint router.IEndpoint endpoint router.IEndPoint
headers []string headers []string
@@ -63,7 +63,7 @@ func (e *EndPoint) Queries() []string {
func NewEndPoint(endpoint router.IEndpoint) *EndPoint { func NewEndPoint(endpoint router.IEndPoint) *EndPoint {
return &EndPoint{endpoint: endpoint} return &EndPoint{endpoint: endpoint}
} }

View File

@@ -9,7 +9,7 @@ import (
) )
type IMatcher interface { type IMatcher interface {
Match(req *http.Request) (service.IService, router.IEndpoint, bool) Match(req *http.Request) (service.IService, router.IEndPoint, bool)
} }
type Matcher struct { type Matcher struct {
@@ -17,7 +17,7 @@ type Matcher struct {
services map[string]service.IService services map[string]service.IService
} }
func (m *Matcher) Match(req *http.Request) (service.IService, router.IEndpoint, bool) { func (m *Matcher) Match(req *http.Request) (service.IService, router.IEndPoint, bool) {
sources := newHttpSources(req) sources := newHttpSources(req)
endpoint, has := m.r.Router(sources) endpoint, has := m.r.Router(sources)

View File

@@ -9,12 +9,12 @@ type ISource interface {
} }
type IRouter interface { type IRouter interface {
Router(source ISource)(endpoint IEndpoint,has bool) Router(source ISource)(endpoint IEndPoint,has bool)
} }
type Routers []IRouter type Routers []IRouter
func (rs Routers) Router(source ISource) ( IEndpoint, bool) { func (rs Routers) Router(source ISource) (IEndPoint, bool) {
for _,r:=range rs{ for _,r:=range rs{
if target,has:=r.Router(source);has{ if target,has:=r.Router(source);has{
return target,has return target,has
@@ -35,7 +35,7 @@ type Node struct {
func (n *Node) Router(source ISource) ( IEndpoint, bool) { func (n *Node) Router(source ISource) (IEndPoint, bool) {
v,has:=source.Get(n.cmd) v,has:=source.Get(n.cmd)
@@ -61,16 +61,16 @@ func (n *Node) Router(source ISource) ( IEndpoint, bool) {
type NodeShut struct { type NodeShut struct {
next IRouter next IRouter
endpoint IEndpoint endpoint IEndPoint
} }
func (n *NodeShut) Router(source ISource) ( IEndpoint, bool) { func (n *NodeShut) Router(source ISource) (IEndPoint, bool) {
if e ,has:=n.next.Router(source);has{ if e ,has:=n.next.Router(source);has{
return e,has return e,has
} }
return n.endpoint,true return n.endpoint,true
} }
func NewNodeShut(next IRouter, endpoint IEndpoint) IRouter { func NewNodeShut(next IRouter, endpoint IEndPoint) IRouter {
return &NodeShut{next: next, endpoint: endpoint} return &NodeShut{next: next, endpoint: endpoint}
} }