2022-01-01 21:47:59 +08:00
|
|
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
|
|
|
|
|
|
|
|
package stats
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
2023-05-20 10:38:17 +08:00
|
|
|
"github.com/TeaOSLab/EdgeNode/internal/utils/fnv"
|
2022-01-01 21:47:59 +08:00
|
|
|
"github.com/mssola/user_agent"
|
2022-01-06 17:05:04 +08:00
|
|
|
"sync"
|
2022-01-01 21:47:59 +08:00
|
|
|
)
|
|
|
|
|
|
2022-01-06 17:05:04 +08:00
|
|
|
var SharedUserAgentParser = NewUserAgentParser()
|
|
|
|
|
|
2022-01-01 21:47:59 +08:00
|
|
|
// UserAgentParser UserAgent解析器
|
|
|
|
|
type UserAgentParser struct {
|
|
|
|
|
parser *user_agent.UserAgent
|
|
|
|
|
|
2023-05-20 10:38:17 +08:00
|
|
|
cacheMap1 map[uint64]UserAgentParserResult
|
|
|
|
|
cacheMap2 map[uint64]UserAgentParserResult
|
2022-01-01 21:47:59 +08:00
|
|
|
maxCacheItems int
|
|
|
|
|
|
|
|
|
|
cacheCursor int
|
2022-01-06 17:05:04 +08:00
|
|
|
locker sync.RWMutex
|
2022-01-01 21:47:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewUserAgentParser() *UserAgentParser {
|
|
|
|
|
var parser = &UserAgentParser{
|
|
|
|
|
parser: &user_agent.UserAgent{},
|
2023-05-20 10:38:17 +08:00
|
|
|
cacheMap1: map[uint64]UserAgentParserResult{},
|
|
|
|
|
cacheMap2: map[uint64]UserAgentParserResult{},
|
2022-01-01 21:47:59 +08:00
|
|
|
cacheCursor: 0,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser.init()
|
|
|
|
|
return parser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *UserAgentParser) init() {
|
|
|
|
|
var maxCacheItems = 10_000
|
|
|
|
|
var systemMemory = utils.SystemMemoryGB()
|
|
|
|
|
if systemMemory >= 16 {
|
|
|
|
|
maxCacheItems = 40_000
|
|
|
|
|
} else if systemMemory >= 8 {
|
|
|
|
|
maxCacheItems = 30_000
|
|
|
|
|
} else if systemMemory >= 4 {
|
|
|
|
|
maxCacheItems = 20_000
|
|
|
|
|
}
|
|
|
|
|
this.maxCacheItems = maxCacheItems
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *UserAgentParser) Parse(userAgent string) (result UserAgentParserResult) {
|
|
|
|
|
// 限制长度
|
|
|
|
|
if len(userAgent) == 0 || len(userAgent) > 256 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 10:38:17 +08:00
|
|
|
var userAgentKey = fnv.HashString(userAgent)
|
|
|
|
|
|
2022-01-06 17:05:04 +08:00
|
|
|
this.locker.RLock()
|
2023-05-20 10:38:17 +08:00
|
|
|
cacheResult, ok := this.cacheMap1[userAgentKey]
|
2022-01-01 21:47:59 +08:00
|
|
|
if ok {
|
2022-01-06 17:05:04 +08:00
|
|
|
this.locker.RUnlock()
|
2022-01-01 21:47:59 +08:00
|
|
|
return cacheResult
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-20 10:38:17 +08:00
|
|
|
cacheResult, ok = this.cacheMap2[userAgentKey]
|
2022-01-01 21:47:59 +08:00
|
|
|
if ok {
|
2022-01-06 17:05:04 +08:00
|
|
|
this.locker.RUnlock()
|
2022-01-01 21:47:59 +08:00
|
|
|
return cacheResult
|
|
|
|
|
}
|
2022-01-06 17:05:04 +08:00
|
|
|
this.locker.RUnlock()
|
2022-01-01 21:47:59 +08:00
|
|
|
|
2022-01-06 17:05:04 +08:00
|
|
|
this.locker.Lock()
|
2023-05-19 20:11:53 +08:00
|
|
|
defer this.locker.Unlock()
|
|
|
|
|
|
2022-01-01 21:47:59 +08:00
|
|
|
this.parser.Parse(userAgent)
|
2022-01-06 17:05:04 +08:00
|
|
|
result.OS = this.parser.OSInfo()
|
|
|
|
|
result.BrowserName, result.BrowserVersion = this.parser.Browser()
|
|
|
|
|
result.IsMobile = this.parser.Mobile()
|
2022-01-01 21:47:59 +08:00
|
|
|
|
2022-11-13 10:32:12 +08:00
|
|
|
// 忽略特殊字符
|
|
|
|
|
if len(result.BrowserName) > 0 {
|
|
|
|
|
for _, r := range result.BrowserName {
|
|
|
|
|
if r == '$' || r == '"' || r == '\'' || r == '<' || r == '>' || r == ')' {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-01 21:47:59 +08:00
|
|
|
if this.cacheCursor == 0 {
|
2023-05-20 10:38:17 +08:00
|
|
|
this.cacheMap1[userAgentKey] = result
|
2022-01-01 21:47:59 +08:00
|
|
|
if len(this.cacheMap1) >= this.maxCacheItems {
|
|
|
|
|
this.cacheCursor = 1
|
2023-05-20 10:38:17 +08:00
|
|
|
this.cacheMap2 = map[uint64]UserAgentParserResult{}
|
2022-01-01 21:47:59 +08:00
|
|
|
}
|
|
|
|
|
} else {
|
2023-05-20 10:38:17 +08:00
|
|
|
this.cacheMap2[userAgentKey] = result
|
2022-01-01 21:47:59 +08:00
|
|
|
if len(this.cacheMap2) >= this.maxCacheItems {
|
|
|
|
|
this.cacheCursor = 0
|
2023-05-20 10:38:17 +08:00
|
|
|
this.cacheMap1 = map[uint64]UserAgentParserResult{}
|
2022-01-01 21:47:59 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|