2024-07-22 16:18:52 +08:00

158 lines
3.0 KiB
Go

package middleware
import (
"f5"
"fmt"
"mt"
"net/http"
"q5"
"strings"
"time"
//. "main/global"
"github.com/gin-gonic/gin"
)
type RedirectInfo struct {
trace_id string
ori_req *gin.Context
sig string
sigtime int64
}
var requestCache = q5.ConcurrentMap[string, []*RedirectInfo]{}
var redirectRequest = q5.ConcurrentMap[string, *RedirectInfo]{}
func CaCheck(c *gin.Context) {
accountId := c.DefaultQuery("account_id", "")
// fmt.Println("ori context:", c)
if accountId == "" || !lockAccount(accountId) {
c.JSON(http.StatusOK, gin.H{
"errcode": 1004,
"errmsg": "Too many requests",
})
return
}
defer unlockAccount(accountId)
action := c.DefaultQuery("a", "")
cache, exist := requestCache.Load(accountId)
if !exist {
pcache := make([]*RedirectInfo, 0, mt.Table.Config.GetMaxCache())
cache = &pcache
}
info := new(RedirectInfo)
info.ori_req = c.Copy()
if !strings.HasSuffix(action, "S") {
CaForward(info)
return
}
info.sigtime = f5.GetApp().GetRealSeconds()
info.trace_id = fmt.Sprintf("%x%02x-%s", info.sigtime, len(*cache), accountId)
info.sig = q5.Md5Str(c.Request.URL.RawQuery + info.trace_id)
if len(*cache) < int(mt.Table.Config.GetMaxCache()) {
*cache = append(*cache, info)
requestCache.Store(accountId, *cache)
} else {
c.JSON(http.StatusOK, gin.H{
"errcode": 1004,
"errmsg": "Too many requests",
})
}
}
func VerifySig(c *gin.Context) {
accountId := c.DefaultQuery("account_id", "")
traceId := c.DefaultQuery("trace_id", "")
sig := c.DefaultQuery("sig", "")
if accountId == "" || traceId == "" || sig == "" {
c.JSON(http.StatusOK, gin.H{
"errcode": 1002,
"errmsg": "empty params",
})
return
}
failresp := gin.H{
"errcode": 1002,
"errmsg": "sig unavailable",
}
req, exist := redirectRequest.Load(accountId)
if !exist {
c.JSON(http.StatusOK, failresp)
return
}
if (*req).sig != sig || (*req).trace_id != traceId ||
(*req).sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) < f5.GetApp().GetRealSeconds() {
c.JSON(http.StatusOK, failresp)
return
}
c.JSON(http.StatusOK, gin.H{
"errcode": 0,
"errmsg": "",
})
}
func CheckRedirect() {
for {
time.Sleep(time.Second)
deletelist := map[string]bool{}
requestCache.Range(func(account string, requests []*RedirectInfo) bool {
_, exist := redirectRequest.Load(account)
if exist {
return true
}
if !lockAccount(account) {
return true
}
var req *RedirectInfo = nil
for len(requests) > 0 {
req = requests[0]
requests = requests[1:]
if req.sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) > f5.GetApp().GetRealSeconds() {
break
}
req = nil
}
if req != nil {
redirectRequest.Store(account, req)
CaForward(req)
}
if len(requests) == 0 {
deletelist[account] = true
}
requestCache.Store(account, requests)
unlockAccount(account)
return true
})
for acc := range deletelist {
list, _ := requestCache.Load(acc)
if len(*list) == 0 {
requestCache.Delete(acc)
accountMutexmap.Delete(acc)
}
}
}
}