mirror of
				https://github.com/eolinker/apinto
				synced 2025-10-31 03:56:24 +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
	 黄孟柱
					黄孟柱