代码拉取完成,页面将自动刷新
package gmqtt
import (
"strings"
"time"
"gitee.com/micro-tools/wf/container/glist"
"gitee.com/micro-tools/wf/text/gregex"
mqtt "github.com/eclipse/paho.mqtt.golang"
)
type (
Request struct {
Client mqtt.Client
Message mqtt.Message
routerMap map[string]string // Router parameters map, which might be nil if there're no router parameters.
}
// handlerParsedItem is the item parsed from URL.Path.
handlerParsedItem struct {
handler *handlerItem // Handler information.
values map[string]string // Router values parsed from URL.Path.
}
// handlerCacheItem is an item just for internal router searching cache.
handlerCacheItem struct {
parsedItems []*handlerParsedItem
hasHook bool
hasServe bool
}
)
const (
routeCacheDuration = time.Hour
)
func (g *GMqtt) getHandlersWithCache(r *Request) {
// Search and cache the router handlers.
value, _ := g.serveCache.GetOrSetFunc(
g.serveHandlerKey(defaultMethod, r.Message.Topic(), defaultDomainName),
func() (interface{}, error) {
parsedItems, hasHook, hasServe := g.searchHandlers(defaultMethod, r.Message.Topic(), defaultDomainName)
if parsedItems != nil {
return &handlerCacheItem{parsedItems, hasHook, hasServe}, nil
}
return nil, nil
}, routeCacheDuration)
if value != nil {
item := value.(*handlerCacheItem)
for _, v := range item.parsedItems {
if v != nil {
if v.values != nil {
for j, k := range v.values {
r.routerMap[j] = k
}
}
v.handler.itemFunc(r)
}
}
}
}
// searchHandlers retrieves and returns the routers with given parameters.
// Note that the returned routers contain serving handler, middleware handlers and hook handlers.
func (g *GMqtt) searchHandlers(method, path, domain string) (parsedItems []*handlerParsedItem, hasHook, hasServe bool) {
if len(path) == 0 {
return nil, false, false
}
// In case of double '/' URI, for example:
// /user//index, //user/index, //user//index//
var previousIsSep = false
for i := 0; i < len(path); {
if path[i] == '/' {
if previousIsSep {
path = path[:i] + path[i+1:]
continue
} else {
previousIsSep = true
}
} else {
previousIsSep = false
}
i++
}
// Split the URL.path to separate parts.
var array []string
if strings.EqualFold("/", path) {
array = []string{"/"}
} else {
array = strings.Split(path[1:], "/")
}
var (
parsedItemList = glist.New()
repeatHandlerCheckMap = make(map[int]struct{}, 16)
)
// Default domain has the most priority when iteration.
for _, domain := range []string{defaultDomainName, domain} {
p, ok := g.serveTree[domain]
if !ok {
continue
}
// Make a list array with capacity of 16.
lists := make([]*glist.List, 0, 16)
for i, part := range array {
// Add all list of each node to the list array.
if v, ok := p.(map[string]interface{})["*list"]; ok {
lists = append(lists, v.(*glist.List))
}
if v, ok := p.(map[string]interface{})[part]; ok {
// Loop to the next node by certain key name.
p = v
if i == len(array)-1 {
if v, ok := p.(map[string]interface{})["*list"]; ok {
lists = append(lists, v.(*glist.List))
break
}
}
} else if v, ok := p.(map[string]interface{})["*fuzz"]; ok {
// Loop to the next node by fuzzy node item.
p = v
}
if i == len(array)-1 {
// It here also checks the fuzzy item,
// for rule case like: "/user/*action" matches to "/user".
if v, ok := p.(map[string]interface{})["*fuzz"]; ok {
p = v
}
// The leaf must have a list item. It adds the list to the list array.
if v, ok := p.(map[string]interface{})["*list"]; ok {
lists = append(lists, v.(*glist.List))
}
}
}
// OK, let's loop the result list array, adding the handler item to the result handler result array.
// As the tail of the list array has the most priority, it iterates the list array from its tail to head.
for i := len(lists) - 1; i >= 0; i-- {
for e := lists[i].Front(); e != nil; e = e.Next() {
item := e.Value.(*handlerItem)
// Filter repeated handler item, especially the middleware and hook handlers.
// It is necessary, do not remove this checks logic unless you really know how it is necessary.
if _, ok := repeatHandlerCheckMap[item.itemId]; ok {
continue
} else {
repeatHandlerCheckMap[item.itemId] = struct{}{}
}
if item.router.Method == defaultMethod || item.router.Method == method {
// Note the rule having no fuzzy rules: len(match) == 1
if match, err := gregex.MatchString(item.router.RegRule, path); err == nil && len(match) > 0 {
parsedItem := &handlerParsedItem{item, nil}
// If the rule contains fuzzy names,
// it needs paring the URL to retrieve the values for the names.
if len(item.router.RegNames) > 0 {
if len(match) > len(item.router.RegNames) {
parsedItem.values = make(map[string]string)
// It there repeated names, it just overwrites the same one.
for i, name := range item.router.RegNames {
parsedItem.values[name] = match[i+1]
}
}
}
hasServe = true
parsedItemList.PushBack(parsedItem)
}
}
}
}
}
if parsedItemList.Len() > 0 {
index := 0
parsedItems = make([]*handlerParsedItem, parsedItemList.Len())
for e := parsedItemList.Front(); e != nil; e = e.Next() {
parsedItems[index] = e.Value.(*handlerParsedItem)
index++
}
}
return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。