158 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|