mirror of
https://github.com/eolinker/apinto
synced 2025-10-30 11:36:34 +08:00
router 驱动
This commit is contained in:
3
go.sum
3
go.sum
@@ -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=
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ const (
|
||||
CheckTypePrefix
|
||||
CheckTypeSuffix
|
||||
CheckTypeNotEqual
|
||||
CheckTypeNull
|
||||
CheckTypeNone
|
||||
CheckTypeExist
|
||||
CheckTypeNotExist
|
||||
CheckTypeRegular
|
||||
|
||||
@@ -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)
|
||||
//}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user