router 驱动

This commit is contained in:
黄孟柱
2021-07-23 19:57:32 +08:00
parent fd21628fa6
commit f8a7e0abe6
15 changed files with 259 additions and 92 deletions

3
go.sum
View File

@@ -6,9 +6,6 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eolinker/eosc v0.0.0-20210719112509-35868a3fa3ed h1:ohyziPArYFDUmaMkjfmy7h7v1vZKxmhERBwb1Vup39U=
github.com/eolinker/eosc v0.0.1 h1:xRDaWSomXpn9E6wVZXE1fQYBpGOeQ2liCwpV4+l+QSc=
github.com/eolinker/eosc v0.0.1/go.mod h1:h9RyDaBnWKeg6fxQu8faG8TQq/sdG+ipaePTTVTEqqA=
github.com/eolinker/eosc v0.0.2 h1:PKSutO9OemDcGyJifNX8EsfOyS73E2ORZmaSJqv4f0M=
github.com/eolinker/eosc v0.0.2/go.mod h1:h9RyDaBnWKeg6fxQu8faG8TQq/sdG+ipaePTTVTEqqA=
github.com/eolinker/goku-standard-plugin v0.1.5 h1:0ydlgjaWsbeQi0le1I7cDrEWTramh5hMdTM7ifG78HM=

View File

@@ -1,5 +1,6 @@
package checker
var globalCheckerAll = &checkerAll{}
type checkerAll struct {
}
@@ -12,10 +13,6 @@ func (t *checkerAll) Value() string {
return "*"
}
func newCheckerAll() *checkerAll {
return &checkerAll{}
}
func (t *checkerAll) Check(v string, has bool) bool {
return true
}
@@ -24,3 +21,6 @@ func (t *checkerAll) CheckType() CheckType {
return CheckTypeAll
}
func newCheckerAll() *checkerAll {
return globalCheckerAll
}

View File

@@ -1,5 +1,9 @@
package checker
var (
globalCheckerExist = &checkerExist{}
globalCheckerNotExist = &checkerNotExits{}
)
type checkerExist struct {
}
@@ -14,7 +18,7 @@ func (t *checkerExist) Value() string {
func newCheckerExist() *checkerExist {
return &checkerExist{}
return globalCheckerExist
}
func (t *checkerExist) Check(v string, has bool) bool {
@@ -46,5 +50,5 @@ func (c *checkerNotExits) CheckType() CheckType {
}
func newCheckerNotExits() *checkerNotExits {
return &checkerNotExits{}
return globalCheckerNotExist
}

View File

@@ -2,6 +2,9 @@ package checker
import "strings"
var (
globalCheckerNone = &checkerNone{}
)
type checkerNone struct {
}
@@ -15,7 +18,7 @@ func (t *checkerNone) Value() string {
}
func newCheckerNone() *checkerNone {
return &checkerNone{}
return globalCheckerNone
}
func (t *checkerNone) Check(v string, has bool) bool {
@@ -26,6 +29,6 @@ func (t *checkerNone) Check(v string, has bool) bool {
}
func (t *checkerNone) CheckType() CheckType {
return CheckTypeNull
return CheckTypeNone
}

View File

@@ -7,7 +7,7 @@ const (
CheckTypePrefix
CheckTypeSuffix
CheckTypeNotEqual
CheckTypeNull
CheckTypeNone
CheckTypeExist
CheckTypeNotExist
CheckTypeRegular

View File

@@ -1,30 +1,35 @@
package http_router
import "net/http"
import (
"github.com/eolinker/eosc"
router_http "github.com/eolinker/goku-eosc/router/router-http"
"github.com/eolinker/goku-eosc/service"
)
type DriverConfig struct {
ID string `json:"id"`
Name string `json:"name" yaml:"name"`
Driver string `json:"driver" yaml:"driver"`
Listen int `json:"listen" yaml:"listen"`
Host []string `json:"host" yaml:"host"`
Rules []DriverRule `json:"rules" yaml:"rules"`
Target eosc.RequireId `json:"target" target:"target" skill:"github.com/eolinker/goku-eosc/service.service.IService"`
}
type DriverRule struct {
Location string `json:"location" yaml:"location"`
Header map[string]string `json:"header" yaml:"header"`
Query map[string]string `json:"query" yaml:"query"`
}
type Config struct {
name string
port int
Rules []RouterRule
rules []router_http.Rule
host []string
service http.Handler
target service.IService
}
type RouterRule struct {
location string
header map[string]string
query map[string]string
}
type RouterWork struct {
Service http.Handler
Config Config
}
//func (r *RouterWork) Start() error {
// routerManager.Add(r.Config, r.Service)
//}
//
//func (r *RouterWork) Stop() error {
// routerManager.Del(r.Config, r.Service)
//}

View File

@@ -1,6 +1,8 @@
package http_router
import (
"fmt"
"github.com/eolinker/goku-eosc/service"
"reflect"
"github.com/eolinker/eosc"
@@ -11,12 +13,34 @@ type HttpRouterDriver struct {
configType reflect.Type
}
func (h *HttpRouterDriver) Create(id, name string, v interface{}, workers map[string]interface{}) (eosc.IWorker, error) {
panic("implement me")
func (h *HttpRouterDriver) Create(id, name string, v interface{}, workers map[eosc.RequireId]interface{}) (eosc.IWorker, error) {
conf, iService, err := h.check(v, workers)
if err!= nil{
return nil,err
}
return NewRouter(id,name,conf,iService),nil
}
func (h*HttpRouterDriver)check(v interface{},workers map[eosc.RequireId]interface{})( *DriverConfig,service.IService,error) {
conf,ok:=v.(*DriverConfig)
if !ok{
return nil, nil,fmt.Errorf("get %s but %s %w",eosc.TypeNameOf(v),eosc.TypeNameOf(new(DriverConfig)),eosc.ErrorRequire)
}
ser,has:=workers[conf.Target]
if !has{
return nil,nil,fmt.Errorf("target %w",eosc.ErrorRequire)
}
target,ok:=ser.(service.IService)
if !ok{
return nil,nil,fmt.Errorf("target %w",eosc.ErrorNotGetSillForRequire)
}
return conf,target,nil
}
func NewHttpRouter(profession, name, label, desc string, params map[string]string) *HttpRouterDriver {
return &HttpRouterDriver{
configType:reflect.TypeOf(new(DriverConfig)),
info: eosc.DriverInfo{
Name: name,
Label: label,

View File

@@ -2,8 +2,17 @@ package http_router
import "github.com/eolinker/eosc"
var (
driverInfo =eosc.ExtendInfo{
ID: "eolinker:goku:http_router",
Group: "eolinker",
Project: "goku",
Name: "http_router",
}
)
func Register() {
eosc.DefaultProfessionDriverRegister.RegisterProfessionDriver("eolinker:goku:http_router",NewRouterDriverFactory())
eosc.DefaultProfessionDriverRegister.RegisterProfessionDriver(driverInfo.ID,NewRouterDriverFactory())
}
type RouterDriverFactory struct {
@@ -11,11 +20,11 @@ type RouterDriverFactory struct {
}
func (r *RouterDriverFactory) ExtendInfo() eosc.ExtendInfo {
panic("implement me")
return driverInfo
}
func (r *RouterDriverFactory) Create(profession string, name string, label string, desc string, params map[string]string) (eosc.IProfessionDriver, error) {
panic("implement me")
return NewHttpRouter(profession,name,label,desc,params),nil
}
func NewRouterDriverFactory() *RouterDriverFactory {

View File

@@ -2,33 +2,97 @@ package http_router
import (
"github.com/eolinker/eosc"
router_http "github.com/eolinker/goku-eosc/router/router-http"
"github.com/eolinker/goku-eosc/service"
)
type Router struct {
id string
name string
port int
conf *router_http.Config
driver * HttpRouterDriver
}
func (r *Router) Marshal() ([]byte, error) {
panic("implement me")
}
func (r *Router) Reset(conf interface{}, workers map[eosc.RequireId]interface{}) error {
cf, target, err := r.driver.check(conf, workers)
if err!= nil{
return err
}
func (r *Router) Worker() (eosc.IWorker, error) {
panic("implement me")
newConf := getConfig(target,cf)
err =router_http.Add(cf.Listen,r.id,newConf)
if err!= nil{
return err
}
if cf.Listen != r.port{
router_http.Del(r.port,r.id)
}
r.port = cf.Listen
r.conf = newConf
return nil
}
func (r *Router) CheckSkill(skill string) bool {
panic("implement me")
return false
}
func (r *Router) Info() eosc.WorkerInfo {
return eosc.WorkerInfo{
Id: "",
Name: "",
Driver: "",
Create: "",
Update: "",
func (r *Router) Id() string {
return r.id
}
func (r *Router) Start() error {
return router_http.Add(r.port,r.id,r.conf)
}
func (r *Router) Stop() error {
return router_http.Del(r.port,r.id)
}
func getConfig(target service.IService,cf *DriverConfig) *router_http.Config {
rules:=make([]router_http.Rule,0,len(cf.Rules))
for _,r:=range cf.Rules{
rr:=router_http.Rule{
Location: r.Location,
Header: make([]router_http.HeaderItem,0,len(r.Header)),
Query: make([]router_http.QueryItem,0,len(r.Query)),
}
for k,v:=range r.Header{
rr.Header = append(rr.Header, router_http.HeaderItem{
Name: k,
Pattern: v,
})
}
for k,v:=range r.Query{
rr.Query = append(rr.Query, router_http.QueryItem{
Name: k,
Pattern: v,
})
}
rules = append(rules, rr)
}
return &router_http.Config{
Id: cf.ID,
Name: cf.Name,
Hosts: cf.Host,
Target: target,
Rules: rules,
}
}
func NewRouter(id,name string,c *DriverConfig,target service.IService) *Router {
return &Router{
id:id,
name:name,
port:c.Listen,
conf:getConfig(target,c),
}
}
func NewRouter(c *Config) *Router {
return &Router{}
}

View File

@@ -15,34 +15,42 @@ import (
)
const (
cmdLocation="LOCATION"
cmdLocation = "LOCATION"
cmdHeader = "HEADER"
cmdQuery = "QUERY"
cmdHost = "HOST"
)
func toLocation()string{
func toLocation() string {
return cmdLocation
}
func toHeader(key string) string {
return fmt.Sprint(cmdHeader ,":",textproto.CanonicalMIMEHeaderKey(key))
return fmt.Sprint(cmdHeader, ":", textproto.CanonicalMIMEHeaderKey(key))
}
func toQuery(key string) string {
return fmt.Sprint(cmdQuery ,":",key)
return fmt.Sprint(cmdQuery, ":", key)
}
func headerName(cmd string) (string,bool) {
if b:= strings.HasPrefix(cmd,"HEADER:");b{
return strings.TrimPrefix(cmd,"HEADER:"),true
func toHost()string {
return cmdHost
}
func headerName(cmd string) (string, bool) {
if b := strings.HasPrefix(cmd, "HEADER:"); b {
return strings.TrimPrefix(cmd, "HEADER:"), true
}
return "",false
return "", false
}
func queryName(cmd string)(string,bool) {
if b:= strings.HasPrefix(cmd,"QUERY:");b{
return strings.TrimPrefix(cmd,"QUERY:"),true
func queryName(cmd string) (string, bool) {
if b := strings.HasPrefix(cmd, "QUERY:"); b {
return strings.TrimPrefix(cmd, "QUERY:"), true
}
return "",false
return "", false
}
func isLocation(cmd string)bool {
return strings.EqualFold(cmd,cmdLocation)
func isLocation(cmd string) bool {
return cmd == cmdLocation
}
func isHost(cmd string) bool {
return cmd == cmdHost
}

View File

@@ -1,11 +1,11 @@
package router_http
import (
"fmt"
"github.com/eolinker/goku-eosc/router"
"github.com/eolinker/goku-eosc/router/checker"
"github.com/eolinker/goku-eosc/service"
"net/textproto"
)
type HeaderItem struct {
@@ -24,6 +24,7 @@ type Rule struct {
type Config struct {
Id string
Name string
Hosts []string
Target service.IService
Rules []Rule
@@ -31,16 +32,19 @@ type Config struct {
func (r *Rule) toPath()([]router.RulePath ,error) {
path:=make([]router.RulePath,0,len(r.Header)+len(r.Query)+1)
if len(r.Location) >0{
locationChecker,err:= checker.Parse(r.Location)
if err!= nil{
return nil,err
}
path:=make([]router.RulePath,0,len(r.Header)+len(r.Query)+1)
path = append(path, router.RulePath{
CMD: toLocation(),
Checker:locationChecker,
} )
}
for _,h:=range r.Header{
ck,err:= checker.Parse(h.Pattern)

View File

@@ -18,7 +18,7 @@ var (
func init() {
n := time.Now().UnixNano()
data := make([]byte, 8)
data := make([]byte, 9)
binary.PutVarint(data, n)
sign = hex.EncodeToString(data)
}

View File

@@ -38,5 +38,29 @@ func newHttpSources(req *http.Request) *HttpSources {
}
func (h *HttpSources) Get(cmd string) (string, bool) {
if isHost(cmd){
return h.req.Host,true
}
if isLocation(cmd){
return h.req.RequestURI,true
}
if hn,yes:=headerName(cmd);yes{
if vs,has:=h.req.Header[hn];has {
if len(vs) == 0{
return "",true
}
return vs[0],true
}
}
if qn,yes:=queryName(cmd);yes{
if vs,has:=h.req.URL.Query()[qn];has{
if len(vs) == 0{
return "",true
}
return vs[0],true
}
}
return "",false
}

View File

@@ -2,6 +2,7 @@ package router_http
import (
"github.com/eolinker/goku-eosc/router"
"github.com/eolinker/goku-eosc/router/checker"
"github.com/eolinker/goku-eosc/service"
)
@@ -9,16 +10,30 @@ func parse(cs []*Config) (IMatcher, error) {
count:=0
for i:=range cs{
count += len(cs[i].Rules)
hsize := len(cs[i].Hosts)
if hsize <1{
hsize = 1
}
count += len(cs[i].Rules)*len(cs[i].Hosts)
}
rules :=make([]router.Rule,0,count)
targets :=make(map[string]service.IService)
for _,c:=range cs{
hosts:=make([]router.RulePath,0,len(c.Hosts))
for _,h:=range c.Hosts{
hck,e:= checker.Parse(h)
if e!= nil{
return nil,e
}
hosts = append(hosts, router.RulePath{
CMD: toHost(),
Checker: hck,
})
}
targets[c.Id]=c.Target
for _,r:=range c.Rules{
@@ -26,12 +41,23 @@ func parse(cs []*Config) (IMatcher, error) {
if err!= nil{
return nil,err
}
if len(hosts) >0{
for _,hp:=range hosts{
pathWidthHost := append(make([]router.RulePath,0,len(path)+1),hp)
pathWidthHost = append(pathWidthHost,path...)
rules = append(rules,router.Rule{
Path:path,
Target:c.Id,
} )
}
}else{
rules = append(rules, router.Rule{
Path:path,
Target:c.Id,
} )
}
}
}
r,err:=router.ParseRouter(rules,NewHttpRouterHelper())
if err!= nil{
return nil,err

View File

@@ -37,8 +37,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
http.NotFound(w, req)
return
}
h.Handle(w,req,nee)
h.Handle(w,req,NewEndPoint(e))
}
func (r *Router) SetRouter(id string, config *Config) error {