mirror of
https://github.com/eolinker/apinto
synced 2025-11-01 12:32:38 +08:00
router fix
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user