From b0dc9064e039b07d4732254d86853b97e30601b4 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 11 Apr 2018 16:06:45 +0800 Subject: [PATCH] =?UTF-8?q?ghttp=E8=B7=AF=E7=94=B1=E4=BC=98=E5=85=88?= =?UTF-8?q?=E7=BA=A7=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/int_bool_map.go | 6 +- g/container/gmap/int_int_map.go | 6 +- g/container/gmap/int_interface_map.go | 6 +- g/container/gmap/int_string_map.go | 6 +- g/container/gmap/interface_interface_map.go | 6 +- g/container/gmap/string_bool_map.go | 6 +- g/container/gmap/string_int_map.go | 6 +- g/container/gmap/string_interface_map.go | 6 +- g/container/gmap/string_string_map.go | 6 +- g/container/gmap/uint_interface_map.go | 6 +- g/container/gset/int_set.go | 6 +- g/container/gset/interface_set.go | 6 +- g/container/gset/string_set.go | 6 +- g/container/gset/uint_set.go | 6 +- g/net/ghttp/http_request.go | 47 +++-- g/net/ghttp/http_server.go | 52 ++---- g/net/ghttp/http_server_domain.go | 22 --- g/net/ghttp/http_server_handler.go | 193 ++++++++++++-------- g/net/grouter/grouter.go | 120 ------------ g/os/gcache/gcache.go | 4 +- geg/net/ghttp/router.go | 2 +- geg/other/test.go | 40 +--- 22 files changed, 234 insertions(+), 330 deletions(-) delete mode 100644 g/net/grouter/grouter.go diff --git a/g/container/gmap/int_bool_map.go b/g/container/gmap/int_bool_map.go index 6e6d0a200..0538876f8 100644 --- a/g/container/gmap/int_bool_map.go +++ b/g/container/gmap/int_bool_map.go @@ -34,10 +34,12 @@ func (this *IntBoolMap) Clone() *map[int]bool { } // 给定回调函数对原始内容进行遍历 -func (this *IntBoolMap) Iterator(f func (k int, v bool)) { +func (this *IntBoolMap) Iterator(f func (k int, v bool) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/int_int_map.go b/g/container/gmap/int_int_map.go index 56bcbda14..fcb3ddd94 100644 --- a/g/container/gmap/int_int_map.go +++ b/g/container/gmap/int_int_map.go @@ -23,10 +23,12 @@ func NewIntIntMap() *IntIntMap { } // 给定回调函数对原始内容进行遍历 -func (this *IntIntMap) Iterator(f func (k int, v int)) { +func (this *IntIntMap) Iterator(f func (k int, v int) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/int_interface_map.go b/g/container/gmap/int_interface_map.go index 2182b5ba3..11d948834 100644 --- a/g/container/gmap/int_interface_map.go +++ b/g/container/gmap/int_interface_map.go @@ -24,10 +24,12 @@ func NewIntInterfaceMap() *IntInterfaceMap { } // 给定回调函数对原始内容进行遍历 -func (this *IntInterfaceMap) Iterator(f func (k int, v interface{})) { +func (this *IntInterfaceMap) Iterator(f func (k int, v interface{}) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/int_string_map.go b/g/container/gmap/int_string_map.go index 90b8f7626..7302b4298 100644 --- a/g/container/gmap/int_string_map.go +++ b/g/container/gmap/int_string_map.go @@ -23,10 +23,12 @@ func NewIntStringMap() *IntStringMap { } // 给定回调函数对原始内容进行遍历 -func (this *IntStringMap) Iterator(f func (k int, v string)) { +func (this *IntStringMap) Iterator(f func (k int, v string) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/interface_interface_map.go b/g/container/gmap/interface_interface_map.go index fb2e21138..9b2640aaa 100644 --- a/g/container/gmap/interface_interface_map.go +++ b/g/container/gmap/interface_interface_map.go @@ -24,10 +24,12 @@ func NewInterfaceInterfaceMap() *InterfaceInterfaceMap { } // 给定回调函数对原始内容进行遍历 -func (this *InterfaceInterfaceMap) Iterator(f func (k interface{}, v interface{})) { +func (this *InterfaceInterfaceMap) Iterator(f func (k interface{}, v interface{}) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/string_bool_map.go b/g/container/gmap/string_bool_map.go index f05c1c200..03915d834 100644 --- a/g/container/gmap/string_bool_map.go +++ b/g/container/gmap/string_bool_map.go @@ -23,10 +23,12 @@ func NewStringBoolMap() *StringBoolMap { } // 给定回调函数对原始内容进行遍历 -func (this *StringBoolMap) Iterator(f func (k string, v bool)) { +func (this *StringBoolMap) Iterator(f func (k string, v bool) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/string_int_map.go b/g/container/gmap/string_int_map.go index 1badb53d2..cec18e057 100644 --- a/g/container/gmap/string_int_map.go +++ b/g/container/gmap/string_int_map.go @@ -23,10 +23,12 @@ func NewStringIntMap() *StringIntMap { } // 给定回调函数对原始内容进行遍历 -func (this *StringIntMap) Iterator(f func (k string, v int)) { +func (this *StringIntMap) Iterator(f func (k string, v int) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/string_interface_map.go b/g/container/gmap/string_interface_map.go index 24130f144..0af9fe28a 100644 --- a/g/container/gmap/string_interface_map.go +++ b/g/container/gmap/string_interface_map.go @@ -24,10 +24,12 @@ func NewStringInterfaceMap() *StringInterfaceMap { } // 给定回调函数对原始内容进行遍历 -func (this *StringInterfaceMap) Iterator(f func (k string, v interface{})) { +func (this *StringInterfaceMap) Iterator(f func (k string, v interface{}) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/string_string_map.go b/g/container/gmap/string_string_map.go index 3c2f01a70..37f5f88ef 100644 --- a/g/container/gmap/string_string_map.go +++ b/g/container/gmap/string_string_map.go @@ -23,10 +23,12 @@ func NewStringStringMap() *StringStringMap { } // 给定回调函数对原始内容进行遍历 -func (this *StringStringMap) Iterator(f func (k string, v string)) { +func (this *StringStringMap) Iterator(f func (k string, v string) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gmap/uint_interface_map.go b/g/container/gmap/uint_interface_map.go index 815498c8d..90f3bc2bc 100644 --- a/g/container/gmap/uint_interface_map.go +++ b/g/container/gmap/uint_interface_map.go @@ -23,10 +23,12 @@ func NewUintInterfaceMap() *UintInterfaceMap { } } -func (this *UintInterfaceMap) Iterator(f func (k uint, v interface{})) { +func (this *UintInterfaceMap) Iterator(f func (k uint, v interface{}) bool) { this.mu.RLock() for k, v := range this.m { - f(k, v) + if !f(k, v) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gset/int_set.go b/g/container/gset/int_set.go index 0efbeaf54..ef0d9d8a5 100644 --- a/g/container/gset/int_set.go +++ b/g/container/gset/int_set.go @@ -23,10 +23,12 @@ func NewIntSet() *IntSet { } // 给定回调函数对原始内容进行遍历 -func (this *IntSet) Iterator(f func (v int)) { +func (this *IntSet) Iterator(f func (v int) bool) { this.mu.RLock() for k, _ := range this.m { - f(k) + if !f(k) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gset/interface_set.go b/g/container/gset/interface_set.go index 93f8dcc3d..216f71cdf 100644 --- a/g/container/gset/interface_set.go +++ b/g/container/gset/interface_set.go @@ -22,10 +22,12 @@ func NewInterfaceSet() *InterfaceSet { } // 给定回调函数对原始内容进行遍历 -func (this *InterfaceSet) Iterator(f func (v interface{})) { +func (this *InterfaceSet) Iterator(f func (v interface{}) bool) { this.mu.RLock() for k, _ := range this.m { - f(k) + if !f(k) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gset/string_set.go b/g/container/gset/string_set.go index f50bc7a49..7e8a42f99 100644 --- a/g/container/gset/string_set.go +++ b/g/container/gset/string_set.go @@ -22,10 +22,12 @@ func NewStringSet() *StringSet { } // 给定回调函数对原始内容进行遍历 -func (this *StringSet) Iterator(f func (v string)) { +func (this *StringSet) Iterator(f func (v string) bool) { this.mu.RLock() for k, _ := range this.m { - f(k) + if !f(k) { + break + } } this.mu.RUnlock() } diff --git a/g/container/gset/uint_set.go b/g/container/gset/uint_set.go index d72021542..884973a2e 100644 --- a/g/container/gset/uint_set.go +++ b/g/container/gset/uint_set.go @@ -22,10 +22,12 @@ func NewUintSet() *UintSet { } // 给定回调函数对原始内容进行遍历 -func (this *UintSet) Iterator(f func (v uint)) { +func (this *UintSet) Iterator(f func (v uint) bool) { this.mu.RLock() for k, _ := range this.m { - f(k) + if !f(k) { + break + } } this.mu.RUnlock() } diff --git a/g/net/ghttp/http_request.go b/g/net/ghttp/http_request.go index 27a785deb..f09812c93 100644 --- a/g/net/ghttp/http_request.go +++ b/g/net/ghttp/http_request.go @@ -9,7 +9,6 @@ package ghttp import ( "io/ioutil" "net/http" - "net/url" "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/encoding/gjson" "gitee.com/johng/gf/g/container/gtype" @@ -18,20 +17,42 @@ import ( // 请求对象 type Request struct { http.Request - parsedPost *gtype.Bool // POST参数是否已经解析 - getvals *url.Values // GET参数 - Id int // 请求id(唯一) - Server *Server // 请求关联的服务器对象 - Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全) - Session *Session // 与当前请求绑定的Session对象(并发安全) - Response *Response // 对应请求的返回数据操作对象 + parsedGet *gtype.Bool // GET参数是否已经解析 + parsedPost *gtype.Bool // POST参数是否已经解析 + values map[string][]string // GET参数 + Id int // 请求id(唯一) + Server *Server // 请求关联的服务器对象 + Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全) + Session *Session // 与当前请求绑定的Session对象(并发安全) + Response *Response // 对应请求的返回数据操作对象 } +// 创建一个Request对象 +func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request { + return &Request{ + parsedGet : gtype.NewBool(), + parsedPost : gtype.NewBool(), + values : make(map[string][]string), + Id : s.servedCount.Add(1), + Server : s, + Request : *r, + Response : &Response { + ResponseWriter : w, + }, + } +} + + // 初始化GET请求参数 func (r *Request) initGet() { - if r.getvals == nil { - values := r.URL.Query() - r.getvals = &values + if !r.parsedGet.Val() { + if len(r.values) == 0 { + r.values = r.URL.Query() + } else { + for k, v := range r.URL.Query() { + r.values[k] = v + } + } } } @@ -48,7 +69,7 @@ func (r *Request) initPost() { // 获得指定名称的get参数列表 func (r *Request) GetQuery(k string) []string { r.initGet() - if v, ok := (*r.getvals)[k]; ok { + if v, ok := r.values[k]; ok { return v } return nil @@ -92,7 +113,7 @@ func (r *Request) GetQueryMap(defaultMap...map[string]string) map[string]string r.initGet() m := make(map[string]string) if len(defaultMap) == 0 { - for k, v := range *r.getvals { + for k, v := range r.values { m[k] = v[0] } } else { diff --git a/g/net/ghttp/http_server.go b/g/net/ghttp/http_server.go index 32807d262..077863fcf 100644 --- a/g/net/ghttp/http_server.go +++ b/g/net/ghttp/http_server.go @@ -12,18 +12,17 @@ import ( "strings" "reflect" "net/http" - "gitee.com/johng/gf/g/util/gutil" - "gitee.com/johng/gf/g/net/grouter" - "gitee.com/johng/gf/g/container/gmap" - "gitee.com/johng/gf/g/container/gqueue" - "gitee.com/johng/gf/g/container/glist" - "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gcache" "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gutil" + "gitee.com/johng/gf/g/container/gmap" + "gitee.com/johng/gf/g/container/glist" + "gitee.com/johng/gf/g/container/gtype" + "gitee.com/johng/gf/g/container/gqueue" ) const ( - gHTTP_METHODS = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE" + gHTTP_METHODS = "GET,POST,DELETE,PUT,PATCH,HEAD,CONNECT,OPTIONS,TRACE" gDEFAULT_SERVER = "default" gDEFAULT_DOMAIN = "default" gDEFAULT_METHOD = "all" @@ -49,10 +48,9 @@ type Server struct { cookieMaxAge *gtype.Int // Cookie有效期 sessionMaxAge *gtype.Int // Session有效期 sessionIdName *gtype.String // SessionId名称 + routers *gcache.Cache // 服务注册路由内存缓存 cookies *gmap.IntInterfaceMap // 当前服务器正在服务(请求正在执行)的Cookie(每个请求一个Cookie对象) sessions *gcache.Cache // Session内存缓存 - - Router *grouter.Router // 路由管理对象 } // 域名、URI与回调函数的绑定记录表 @@ -81,14 +79,14 @@ func GetServer(names...string) (*Server) { if s := serverMapping.Get(name); s != nil { return s.(*Server) } - s := &Server{ + s := &Server { name : name, handlerMap : make(HandlerMap), methodsMap : make(map[string]bool), servedCount : gtype.NewInt(), closeQueue : gqueue.New(), hooksMap : gmap.NewStringInterfaceMap(), - Router : grouter.New(), + routers : gcache.New(), cookies : gmap.NewIntInterfaceMap(), sessions : gcache.New(), cookieMaxAge : gtype.NewInt(gDEFAULT_COOKIE_MAX_AGE), @@ -103,7 +101,7 @@ func GetServer(names...string) (*Server) { return s } -// 执行 +// 阻塞执行监听 func (s *Server) Run() error { if s.status == 1 { return errors.New("server is already running") @@ -137,7 +135,7 @@ func (s *Server) handlerKey(domain, method, pattern string) string { return strings.ToUpper(method) + ":" + pattern + "@" + strings.ToLower(domain) } -// 设置请求处理方法 +// 注册服务处理方法 func (s *Server) setHandler(domain, method, pattern string, item HandlerItem) { s.hmu.Lock() defer s.hmu.Unlock() @@ -330,8 +328,7 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, methods strin return s.bindHandlerByMap(m) } -// 绑定指定的hook回调函数, hook参数的值由ghttp server设定,参数不区分大小写 -// 目前hook支持:Init/Shut +// 绑定指定的hook回调函数, pattern参数同BindHandler,支持命名路由;hook参数的值由ghttp server设定,参数不区分大小写 func (s *Server)BindHookHandler(pattern string, hook string, handler HandlerFunc) error { domain, method, uri, err := s.parsePatternForBindHandler(pattern) if err != nil { @@ -364,32 +361,7 @@ func (s *Server)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerF return nil } -//// 绑定URI服务注册的Init回调函数,回调时按照注册顺序执行 -//// Init回调调用时机为请求进入控制器之前,初始化Request对象之后 -//func (s *Server)BindHookHandlerInit(pattern string, handler HandlerFunc) error { -// return s.BindHookHandler(pattern, "Init", handler) -//} -// -//// 绑定URI服务注册的Shut回调函数,回调时按照注册顺序执行 -//// Shut回调调用时机为请求执行完成之后,所有的请求资源释放之前 -//func (s *Server)BindHookHandlerShut(pattern string, handler HandlerFunc) error { -// return s.BindHookHandler(pattern, "Shut", handler) -//} - // 构造用于hooksMap检索的键名 func (s *Server)handlerHookKey(domain, method, uri, hook string) string { return strings.ToUpper(hook) + "^" + s.handlerKey(domain, method, uri) } - -// 获取指定hook的回调函数列表,按照注册顺序排序 -func (s *Server)getHookList(domain, method, uri, hook string) []HandlerFunc { - if v := s.hooksMap.Get(s.handlerHookKey(domain, method, uri, hook)); v != nil { - items := v.(*glist.List).FrontAll() - funcs := make([]HandlerFunc, len(items)) - for k, v := range items { - funcs[k] = v.(HandlerFunc) - } - return funcs - } - return nil -} \ No newline at end of file diff --git a/g/net/ghttp/http_server_domain.go b/g/net/ghttp/http_server_domain.go index 3a11a6523..afbbe6ea0 100644 --- a/g/net/ghttp/http_server_domain.go +++ b/g/net/ghttp/http_server_domain.go @@ -128,25 +128,3 @@ func (d *Domain)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerF } return nil } - -//// 绑定URI服务注册的Init回调函数,回调时按照注册顺序执行 -//// Init回调调用时机为请求进入控制器之前,初始化Request对象之后 -//func (d *Domain)BindHookHandlerInit(pattern string, handler HandlerFunc) error { -// for domain, _ := range d.m { -// if err := d.s.BindHookHandlerInit(pattern + "@" + domain, handler); err != nil { -// return err -// } -// } -// return nil -//} -// -//// 绑定URI服务注册的Shut回调函数,回调时按照注册顺序执行 -//// Shut回调调用时机为请求执行完成之后,所有的请求资源释放之前 -//func (d *Domain)BindHookHandlerShut(pattern string, handler HandlerFunc) error { -// for domain, _ := range d.m { -// if err := d.s.BindHookHandlerShut(pattern + "@" + domain, handler); err != nil { -// return err -// } -// } -// return nil -//} \ No newline at end of file diff --git a/g/net/ghttp/http_server_handler.go b/g/net/ghttp/http_server_handler.go index e19318773..29d353b4d 100644 --- a/g/net/ghttp/http_server_handler.go +++ b/g/net/ghttp/http_server_handler.go @@ -13,14 +13,14 @@ import ( "sort" "reflect" "strings" + "strconv" "net/url" "net/http" "path/filepath" "gitee.com/johng/gf/g/os/gfile" - "gitee.com/johng/gf/g/encoding/ghtml" - "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/util/gregx" - "strconv" + "gitee.com/johng/gf/g/encoding/ghtml" + "gitee.com/johng/gf/g/container/glist" ) // 默认HTTP Server处理入口,http包底层默认使用了gorutine异步处理请求,所以这里不再异步执行 @@ -33,22 +33,7 @@ func (s *Server)defaultHttpHandle(w http.ResponseWriter, r *http.Request) { // 其次,如果没有对应的自定义处理接口配置,那么走默认的域名处理接口配置; // 最后,如果以上都没有找到处理接口,那么进行文件处理; func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) { - // 全局路由解析 - uri := r.URL.String() - result, err := s.Router.Dispatch(uri) - if err == nil && strings.Compare(uri, result) != 0 { - r.URL, _ = r.URL.Parse(result) - } - // 构造请求参数对象 - request := &Request{ - parsedPost : gtype.NewBool(), - Id : s.servedCount.Add(1), - Server : s, - Request : *r, - Response : &Response { - ResponseWriter : w, - }, - } + request := newRequest(s, r, w) if h := s.getHandler(request); h != nil { s.callHandler(h, request) } else { @@ -57,7 +42,14 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) { } // 查询请求处理方法 +// 这里有个锁机制,可以并发读,但是不能并发写 func (s *Server) getHandler(r *Request) *HandlerItem { + handler := s.searchHandler(r) + return handler +} + +// 服务方法检索 +func (s *Server) searchHandler(r *Request) *HandlerItem { s.hmu.RLock() defer s.hmu.RUnlock() domains := []string{gDEFAULT_DOMAIN, strings.Split(r.Host, ":")[0]} @@ -71,23 +63,28 @@ func (s *Server) getHandler(r *Request) *HandlerItem { for k, v := range s.handlerMap { if array, err := gregx.MatchString(`([a-zA-Z]+):(.+)@([\w\.\-]+)`, k); len(array) > 2 && err == nil { // method匹配 - if strings.EqualFold(r.Method, array[1]) { - for _, domain := range domains { - // domain匹配 - if !strings.EqualFold(domain, array[3]) { - continue - } - // method & domain匹配时,那么执行pattern的正则匹配 - regrule, querystr := s.patternToRegRule(array[2]) - if gregx.IsMatchString(regrule, r.URL.Path) { - // 如果需要query匹配,那么需要重新解析URL - if len(querystr) > 0 { - if result, err := gregx.ReplaceString(regrule, querystr, r.URL.Path); err == nil { - r.URL, _ = r.URL.Parse(r.URL.Path + "?" + r.URL.RawQuery + "&" + result) + if !strings.EqualFold(r.Method, array[1]) { + continue + } + // domain匹配 + for _, domain := range domains { + if !strings.EqualFold(domain, array[3]) { + continue + } + // method & domain匹配时,那么执行pattern的正则匹配 + regrule, querystr := s.patternToRegRule(array[2]) + if gregx.IsMatchString(regrule, r.URL.Path) { + // 如果需要query匹配,那么需要重新解析URL + if len(querystr) > 0 { + if query, err := gregx.ReplaceString(regrule, querystr, r.URL.Path); err == nil && len(query) > 0 { + if vals, err := url.ParseQuery(query); err == nil { + for k, v := range vals { + r.values[k] = v + } } } - return &v } + return &v } } } @@ -95,29 +92,103 @@ func (s *Server) getHandler(r *Request) *HandlerItem { return nil } + +// 按照指定hook回调函数的注册顺序进行调用 +func (s *Server)callHookHandler(r *Request, hook string) { + l := s.searchHookHandler(r, hook) + if l != nil { + for _, f := range l { + f(r) + } + } +} + +// 获取指定hook的回调函数列表,按照注册顺序排序 +func (s *Server)searchHookHandler(r *Request, hook string) []HandlerFunc { + domains := []string{gDEFAULT_DOMAIN, strings.Split(r.Host, ":")[0]} + // 首先进行静态匹配 + for _, domain := range domains { + key := s.handlerHookKey(domain, r.Method, r.URL.Path, hook) + if v := s.hooksMap.Get(key); v != nil { + items := v.(*glist.List).FrontAll() + funcs := make([]HandlerFunc, len(items)) + for k, v := range items { + funcs[k] = v.(HandlerFunc) + } + return funcs + } + } + // 其次进行正则匹配(会比较耗效率) + var funcs []HandlerFunc + s.hooksMap.Iterator(func(rule string, list interface{}) bool { + if array, err := gregx.MatchString(`([a-zA-Z]+)\^([a-zA-Z]+):(.+)@([\w\.\-]+)`, rule); len(array) > 3 && err == nil { + // hook匹配 + if !strings.EqualFold(hook, array[1]) { + return true + } + // method匹配 + if !strings.EqualFold(r.Method, array[2]) { + return true + } + // domain匹配 + for _, domain := range domains { + if !strings.EqualFold(domain, array[4]) { + continue + } + // method & domain匹配时,那么执行pattern的正则匹配 + regrule, querystr := s.patternToRegRule(array[3]) + if gregx.IsMatchString(regrule, r.URL.Path) { + // 如果需要query匹配,那么需要重新解析URL + if len(querystr) > 0 { + if query, err := gregx.ReplaceString(regrule, querystr, r.URL.Path); err == nil && len(query) > 0 { + if vals, err := url.ParseQuery(query); err == nil { + for k, v := range vals { + r.values[k] = v + } + } + } + } + // 列表数据解析 + items := list.(*glist.List).FrontAll() + funcs = make([]HandlerFunc, len(items)) + for k, v := range items { + funcs[k] = v.(HandlerFunc) + } + return false + } + } + } + return true + }) + return funcs +} + // 将pattern(不带method和domain)解析成正则表达式匹配以及对应的query字符串 func (s *Server) patternToRegRule(rule string) (regrule string, querystr string) { - regrule = "/" + if len(rule) < 2 { + return rule, "" + } + regrule = "^/" array := strings.Split(rule[1:], "/") index := 1 for _, v := range array { switch v[0] { - case ':': - regrule += `/([\w\.\-]+)` - if len(querystr) > 0 { - querystr += "&" - } - querystr += v[1:] + "=$" + strconv.Itoa(index) - index++ - case '*': - regrule += `/(.*)` - if len(querystr) > 0 { - querystr += "&" - } - querystr += v[1:] + "=$" + strconv.Itoa(index) - return - default: - regrule += v + case ':': + regrule += `/([\w\.\-]+)` + if len(querystr) > 0 { + querystr += "&" + } + querystr += v[1:] + "=$" + strconv.Itoa(index) + index++ + case '*': + regrule += `/(.*)` + if len(querystr) > 0 { + querystr += "&" + } + querystr += v[1:] + "=$" + strconv.Itoa(index) + return + default: + regrule += v } } return @@ -142,14 +213,6 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) { } s.callHookHandler(r, "AfterServe") - // 路由规则打包 - s.callHookHandler(r, "BeforePatch") - if buffer, err := s.Router.Patch(r.Response.Buffer()); err == nil { - r.Response.ClearBuffer() - r.Response.Write(buffer) - } - s.callHookHandler(r, "AfterPatch") - s.callHookHandler(r, "BeforeOutput") // 输出Cookie @@ -163,20 +226,6 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) { s.closeQueue.PushBack(r) } -// 按照指定hook回调函数的注册顺序进行调用 -func (s *Server)callHookHandler(r *Request, hook string) { - l := s.getHookList(gDEFAULT_DOMAIN, r.Method, r.URL.Path, hook) - if l == nil { - l = s.getHookList(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path, hook) - } - if l == nil { - return - } - for _, f := range l { - f(r) - } -} - // 处理静态文件请求 func (s *Server)serveFile(w http.ResponseWriter, r *http.Request) { uri := r.URL.String() diff --git a/g/net/grouter/grouter.go b/g/net/grouter/grouter.go deleted file mode 100644 index e4b0f7684..000000000 --- a/g/net/grouter/grouter.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://gitee.com/johng/gf. -// - -// 路由管理. -// 路由规则按照传入的优先级进行解析 -package grouter - -import ( - "sync" - "bytes" - "errors" - "strings" - "gitee.com/johng/gf/g/util/gregx" - "gitee.com/johng/gf/g/container/gmap" - "gitee.com/johng/gf/g/util/gutil" -) - -// 路由管理对象 -type Router struct { - dmu sync.RWMutex // 解析规则互斥锁 - pmu sync.RWMutex // 打包规则互斥锁 - dkeys []string // 解析规则排序键名 - pkeys []string // 打包规则排序键名 - drules *gmap.StringStringMap // dispatch解析规则 - prules *gmap.StringStringMap // patch打包规则 -} - -func New() *Router { - return &Router{ - drules : gmap.NewStringStringMap(), - prules : gmap.NewStringStringMap(), - } -} - -// 设置解析规则,例如:静态分页 -// `\/([\w\.\-]+)\/([\w\.\-]+)\/page\/([\d\.\-]+)[\/\?]*`, "/user/list/page/2" -func (r *Router) SetRule(rule, replace string) { - r.drules.Set(rule, replace) - if !gutil.StringInArray(r.dkeys, rule) { - r.dmu.Lock() - r.dkeys = append(r.dkeys, rule) - r.dmu.Unlock() - } -} - -// 删除解析规则 -func (r *Router) RemoveRule(rule string) { - if i := gutil.StringSearch(r.dkeys, rule); i != -1 { - r.drules.Remove(rule) - r.dmu.Lock() - r.dkeys = append(r.dkeys[ : i], r.dkeys[i + 1 : ]...) - r.dmu.Unlock() - } -} - -// 设置打包规则 -func (r *Router) SetPatchRule(rule, replace string) { - r.prules.Set(rule, replace) - if !gutil.StringInArray(r.pkeys, rule) { - r.pmu.Lock() - r.pkeys = append(r.pkeys, rule) - r.pmu.Unlock() - } -} - -// 删除打包规则 -func (r *Router) RemovePatchRule(rule string) { - if i := gutil.StringSearch(r.pkeys, rule); i != -1 { - r.prules.Remove(rule) - r.pmu.Lock() - r.pkeys = append(r.pkeys[ : i], r.pkeys[i + 1 : ]...) - r.pmu.Unlock() - } -} - -// 解析URI -func (r *Router) Dispatch(uri string) (string, error) { - r.dmu.RLock() - defer r.dmu.RUnlock() - if len(r.dkeys) == 0 { - return uri, errors.New("no dispatch rules found") - } - for _, rule := range r.dkeys { - if replace := r.drules.Get(rule); replace != "" { - result, err := gregx.ReplaceString(rule, replace, uri) - if err != nil { - return result, err - } - if len(uri) != len(result) || strings.Compare(result, uri) != 0 { - return result, nil - } - } - } - return uri, nil -} - -// 打包内容 -func (r *Router) Patch(content []byte) ([]byte, error) { - r.pmu.RLock() - defer r.pmu.RUnlock() - if len(r.pkeys) == 0 { - return content, errors.New("no patch rules found") - } - for _, rule := range r.pkeys { - if replace := r.prules.Get(rule); replace != "" { - result, err := gregx.Replace(rule, []byte(replace), content) - if err != nil { - return result, err - } - if len(content) != len(result) || bytes.Compare(result, content) != 0 { - return result, nil - } - } - } - return content, nil -} \ No newline at end of file diff --git a/g/os/gcache/gcache.go b/g/os/gcache/gcache.go index ad0ae5a40..2fbde1ac6 100644 --- a/g/os/gcache/gcache.go +++ b/g/os/gcache/gcache.go @@ -334,7 +334,7 @@ func (c *Cache) autoClearLoop() { } // 删除对应键名的缓存数据 -func (c *Cache) clearByKey(key string) { +func (c *Cache) clearByKey(key string) bool { // 删除缓存数据 c.dmu.Lock() delete(c.data, key) @@ -347,4 +347,6 @@ func (c *Cache) clearByKey(key string) { // 删除LRU管理对象中指定键名 c.lru.Remove(key) + + return true } diff --git a/geg/net/ghttp/router.go b/geg/net/ghttp/router.go index 49309bec8..2c5310131 100644 --- a/geg/net/ghttp/router.go +++ b/geg/net/ghttp/router.go @@ -3,7 +3,7 @@ package main import "gitee.com/johng/gf/g/net/ghttp" func main () { - ghttp.GetServer().BindHandler("/router/:name", func(r *ghttp.Request) { + ghttp.GetServer().BindHandler("/router/*name", func(r *ghttp.Request) { r.Response.WriteString(r.GetQueryString("name")) }) ghttp.GetServer().SetPort(10000) diff --git a/geg/other/test.go b/geg/other/test.go index c003da880..17f642a51 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,42 +1,16 @@ package main import ( - "strings" "fmt" "gitee.com/johng/gf/g/util/gregx" - "strconv" + "gitee.com/johng/gf/g/os/gtime" ) -func ruleToRegx(rule string) (regrule string, querystr string) { - regrule = "/" - array := strings.Split(rule[1:], "/") - index := 1 - for _, v := range array { - switch v[0] { - case ':': - regrule += `/([\w\.\-]+)` - if len(querystr) > 0 { - querystr += "&" - } - querystr += v[1:] + "=$" + strconv.Itoa(index) - index++ - case '*': - regrule += `/(.*)` - if len(querystr) > 0 { - querystr += "&" - } - querystr += v[1:] + "=$" + strconv.Itoa(index) - return - default: - regrule += v - } - } - return -} - func main() { - fmt.Println(strings.Compare("A", "A")) - fmt.Println(gregx.MatchString(`(\w+):(.+)@([\w\.\-]+)`, "get/users/name/*action@www.johng-cn.com")) - fmt.Println(ruleToRegx("/users/:name/*action")) - fmt.Println(gregx.IsMatch(`/users/([\w\.\-]+)/(.*)`, []byte("/users/john/aa/aa/aa"))) + t1 := gtime.Microsecond() + for i := 0; i < 10000; i++ { + gregx.MatchString(`([a-zA-Z]+)\^([a-zA-Z]+):(.+)@([\w\.\-]+)`, "a^b:c@d") + } + t2 := gtime.Microsecond() + fmt.Println(t2 - t1) } \ No newline at end of file