mirror of
https://github.com/eolinker/apinto
synced 2025-11-01 04:22:40 +08:00
router fix
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/eolinker/goku-eosc/router/checker"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RulePath struct {
|
||||
@@ -29,16 +30,16 @@ type ICreateHelper interface {
|
||||
|
||||
//ParseRouter parse rule to IRouter
|
||||
func ParseRouter(rules []Rule,helper ICreateHelper)(IRouter,error) {
|
||||
root:=newCreateRoot()
|
||||
root:=newCreateRoot(helper)
|
||||
|
||||
for i:=range rules{
|
||||
r:=rules[i]
|
||||
err:=root.add(r.Path,NewEndpoint(r.Target,r.Path))
|
||||
err:=root.add(r.Path,r.Target)
|
||||
if err!= nil{
|
||||
return nil,err
|
||||
}
|
||||
}
|
||||
return root.toRouter(helper ),nil
|
||||
return root.toRouter( ),nil
|
||||
}
|
||||
|
||||
type createNodes map[string]*createNode
|
||||
@@ -87,6 +88,7 @@ type createNodeList struct {
|
||||
ICreateHelper
|
||||
}
|
||||
|
||||
|
||||
func (cl *createNodeList) Len() int {
|
||||
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]
|
||||
}
|
||||
|
||||
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 {
|
||||
helper ICreateHelper
|
||||
nexts createNodes
|
||||
}
|
||||
|
||||
func newCreateRoot() *createRoot {
|
||||
func newCreateRoot(helper ICreateHelper) *createRoot {
|
||||
return &createRoot{
|
||||
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
|
||||
Get(CMD string)(checker.Checker,bool)
|
||||
Target()string
|
||||
EndPoint()string
|
||||
}
|
||||
type tEndpoint struct {
|
||||
target string
|
||||
cmds []string
|
||||
checkers map[string]checker.Checker
|
||||
endpoint string
|
||||
}
|
||||
|
||||
func (e *tEndpoint) CMDs() []string {
|
||||
@@ -137,26 +160,44 @@ func (e *tEndpoint) Get(CMD string) (checker.Checker,bool) {
|
||||
func (e *tEndpoint) Target() string {
|
||||
return e.target
|
||||
}
|
||||
func (e *tEndpoint)EndPoint()string {
|
||||
|
||||
return e.target
|
||||
}
|
||||
|
||||
func NewEndpoint(target string, path []RulePath) *tEndpoint {
|
||||
cs:=make(map[string]checker.Checker)
|
||||
cmds:=make([]string,0,len(path))
|
||||
build:=strings.Builder{}
|
||||
|
||||
for _,p:=range path{
|
||||
cs[p.CMD] = p.Checker
|
||||
cmds = append(cmds, p.CMD)
|
||||
|
||||
build.WriteString(p.CMD)
|
||||
build.WriteString(p.Checker.Key())
|
||||
build.WriteString("&")
|
||||
}
|
||||
return &tEndpoint{target: target, checkers:cs,cmds:cmds}
|
||||
|
||||
return &tEndpoint{target: target, checkers:cs,cmds:cmds,endpoint:build.String()}
|
||||
}
|
||||
|
||||
func (e *tEndpoint) Router(source ISource) (endpoint IEndpoint, has bool) {
|
||||
func (e *tEndpoint) Router(source ISource) (endpoint IEndPoint, has bool) {
|
||||
return e,e!= nil
|
||||
}
|
||||
|
||||
func (cr *createRoot) add(path []RulePath,endpoint *tEndpoint) error {
|
||||
if len(path) == 0 || endpoint == nil {
|
||||
func (cr *createRoot) add(path []RulePath,target string) error {
|
||||
|
||||
if len(path) == 0 || target == "" {
|
||||
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 {
|
||||
@@ -193,7 +234,7 @@ func (cc *createChecker) toRouter(helper ICreateHelper) IRouter {
|
||||
func (cc *createChecker) add(path []RulePath,endpoint *tEndpoint) error {
|
||||
if len(path) == 0 {
|
||||
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
|
||||
return nil
|
||||
|
||||
@@ -425,13 +425,13 @@ var tests = []struct {
|
||||
},
|
||||
},
|
||||
want: []string{"demo2", "demo3"},
|
||||
wantErr: true,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestParseRouter(t *testing.T) {
|
||||
|
||||
helper := NewTestHelper([]string{"location", "header", "query"})
|
||||
helper := NewTestHelper([]string{"host","location", "header", "query"})
|
||||
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
return
|
||||
}
|
||||
if tt.wantErr{
|
||||
t.Logf("ParseRouter() error = %v ok", err)
|
||||
return
|
||||
}
|
||||
|
||||
for i, s := range tt.testCase {
|
||||
endpoint, h := r.Router(s)
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
var _ service.IRouterEndpoint = (*EndPoint)(nil)
|
||||
type EndPoint struct {
|
||||
endpoint router.IEndpoint
|
||||
endpoint router.IEndPoint
|
||||
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type IMatcher interface {
|
||||
Match(req *http.Request) (service.IService, router.IEndpoint, bool)
|
||||
Match(req *http.Request) (service.IService, router.IEndPoint, bool)
|
||||
}
|
||||
|
||||
type Matcher struct {
|
||||
@@ -17,7 +17,7 @@ type Matcher struct {
|
||||
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)
|
||||
endpoint, has := m.r.Router(sources)
|
||||
|
||||
@@ -9,12 +9,12 @@ type ISource interface {
|
||||
}
|
||||
|
||||
type IRouter interface {
|
||||
Router(source ISource)(endpoint IEndpoint,has bool)
|
||||
Router(source ISource)(endpoint IEndPoint,has bool)
|
||||
}
|
||||
|
||||
type Routers []IRouter
|
||||
|
||||
func (rs Routers) Router(source ISource) ( IEndpoint, bool) {
|
||||
func (rs Routers) Router(source ISource) (IEndPoint, bool) {
|
||||
for _,r:=range rs{
|
||||
if target,has:=r.Router(source);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)
|
||||
|
||||
@@ -61,16 +61,16 @@ func (n *Node) Router(source ISource) ( IEndpoint, bool) {
|
||||
|
||||
type NodeShut struct {
|
||||
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{
|
||||
return e,has
|
||||
}
|
||||
return n.endpoint,true
|
||||
}
|
||||
|
||||
func NewNodeShut(next IRouter, endpoint IEndpoint) IRouter {
|
||||
func NewNodeShut(next IRouter, endpoint IEndPoint) IRouter {
|
||||
return &NodeShut{next: next, endpoint: endpoint}
|
||||
}
|
||||
Reference in New Issue
Block a user