diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index 1bea05337..0293e743c 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -89,6 +89,8 @@ type Router struct { Uri string // 注册时的pattern - uri Method string // 注册时的pattern - method Domain string // 注册时的pattern - domain + RegRule string // 路由规则解析后对应的正则表达式 + RegNames []string // 路由规则解析后对应的变量名称数组 Priority int // 优先级,用于链表排序,值越大优先级越高 } diff --git a/g/net/ghttp/ghttp_server_hooks.go b/g/net/ghttp/ghttp_server_hooks.go index d4ee82617..42eeb9501 100644 --- a/g/net/ghttp/ghttp_server_hooks.go +++ b/g/net/ghttp/ghttp_server_hooks.go @@ -32,6 +32,7 @@ func (s *Server) setHookHandler(pattern string, hook string, item *HandlerItem) Domain : domain, Method : method, } + item.router.RegRule, item.router.RegNames = s.patternToRegRule(uri) s.hhmu.Lock() defer s.hhmu.Unlock() @@ -52,18 +53,13 @@ func (s *Server) setHookHandler(pattern string, hook string, item *HandlerItem) if len(v) == 0 { continue } - switch v[0] { - case ':': - fallthrough - case '*': - v = "/" - fallthrough - default: - if _, ok := p.(map[string]interface{})[v]; !ok { - p.(map[string]interface{})[v] = make(map[string]interface{}) - } - p = p.(map[string]interface{})[v] + if gregex.IsMatchString(`^[:\*]|{[\w\.\-]+}`, v) { + v = "*fuzz" } + if _, ok := p.(map[string]interface{})[v]; !ok { + p.(map[string]interface{})[v] = make(map[string]interface{}) + } + p = p.(map[string]interface{})[v] } // 到达叶子节点 var l *list.List @@ -77,7 +73,7 @@ func (s *Server) setHookHandler(pattern string, hook string, item *HandlerItem) for e := l.Front(); e != nil; e = e.Next() { if s.compareHandlerItemPriority(item, e.Value.(*HandlerItem)) { l.InsertBefore(item, e) - return nil + break } } l.PushBack(item) diff --git a/g/net/ghttp/ghttp_server_router.go b/g/net/ghttp/ghttp_server_router.go index 32d64c3d6..cac62c0b4 100644 --- a/g/net/ghttp/ghttp_server_router.go +++ b/g/net/ghttp/ghttp_server_router.go @@ -21,28 +21,28 @@ type handlerCacheItem struct { } // 查询请求处理方法 -// 这里有个锁机制,可以并发读,但是不能并发写 +// 内部带锁机制,可以并发读,但是不能并发写;并且有缓存机制,按照Host、Method、Path进行缓存 func (s *Server) getHandler(r *Request) *HandlerItem { // 缓存清空时是直接修改属性,因此必须使用互斥锁 s.hmcmu.RLock() defer s.hmcmu.RUnlock() - var handlerItem *handlerCacheItem + var cacheItem *handlerCacheItem cacheKey := s.handlerKey(r.GetHost(), r.Method, r.URL.Path) if v := s.handlerCache.Get(cacheKey); v == nil { - handlerItem = s.searchHandler(r) - if handlerItem != nil { - s.handlerCache.Set(cacheKey, handlerItem, 0) + cacheItem = s.searchHandler(r) + if cacheItem != nil { + s.handlerCache.Set(cacheKey, cacheItem, 0) } } else { - handlerItem = v.(*handlerCacheItem) + cacheItem = v.(*handlerCacheItem) } - if handlerItem != nil { - for k, v := range handlerItem.values { + if cacheItem != nil { + for k, v := range cacheItem.values { r.queries[k] = v } - r.Router = handlerItem.item.router - return handlerItem.item + r.Router = cacheItem.item.router + return cacheItem.item } return nil } @@ -81,6 +81,7 @@ func (s *Server) setHandler(pattern string, item *HandlerItem) error { Domain : domain, Method : method, } + item.router.RegRule, item.router.RegNames = s.patternToRegRule(uri) s.hmmu.Lock() defer s.hmmu.Unlock() defer s.clearHandlerCache() @@ -251,23 +252,15 @@ func (s *Server) searchHandlerDynamic(r *Request) *handlerCacheItem { item := e.Value.(*HandlerItem) // 动态匹配规则带有gDEFAULT_METHOD的情况,不会像静态规则那样直接解析为所有的HTTP METHOD存储 if strings.EqualFold(item.router.Method, gDEFAULT_METHOD) || strings.EqualFold(item.router.Method, r.Method) { - // 不管正则关键字符转义问题 - //rule, names := s.patternToRegRule(gstr.ReplaceByMap(gregex.Quote(item.router.Uri), map[string]string { - // `\{` : `{`, - // `\}` : `}`, - // `\*` : `*`, - //})) - rule, names := s.patternToRegRule(item.router.Uri) - if match, err := gregex.MatchString(rule, r.URL.Path); err == nil && len(match) > 1 { + if match, err := gregex.MatchString(item.router.RegRule, r.URL.Path); err == nil && len(match) > 1 { //gutil.Dump(match) //gutil.Dump(names) handlerItem := &handlerCacheItem{item, nil} // 如果需要query匹配,那么需要重新正则解析URL - if len(names) > 0 { - array := strings.Split(names, ",") - if len(match) > len(array) { + if len(item.router.RegNames) > 0 { + if len(match) > len(item.router.RegNames) { handlerItem.values = make(map[string][]string) - for index, name := range array { + for index, name := range item.router.RegNames { handlerItem.values[name] = []string{match[index + 1]} } } @@ -282,9 +275,9 @@ func (s *Server) searchHandlerDynamic(r *Request) *handlerCacheItem { } // 将pattern(不带method和domain)解析成正则表达式匹配以及对应的query字符串 -func (s *Server) patternToRegRule(rule string) (regrule string, names string) { +func (s *Server) patternToRegRule(rule string) (regrule string, names []string) { if len(rule) < 2 { - return rule, "" + return rule, nil } regrule = "^" array := strings.Split(rule[1:], "/") @@ -295,22 +288,13 @@ func (s *Server) patternToRegRule(rule string) (regrule string, names string) { switch v[0] { case ':': regrule += `/([\w\.\-]+)` - if len(names) > 0 { - names += "," - } - names += v[1:] + names = append(names, v[1:]) case '*': regrule += `/{0,1}(.*)` - if len(names) > 0 { - names += "," - } - names += v[1:] + names = append(names, v[1:]) default: s, _ := gregex.ReplaceStringFunc(`{[\w\.\-]+}`, v, func(s string) string { - if len(names) > 0 { - names += "," - } - names += s[1 : len(s) - 1] + names = append(names, s[1 : len(s) - 1]) return `([\w\.\-]+)` }) if strings.EqualFold(s, v) {