wp-go/app/middleware/iplimit.go

80 lines
1.4 KiB
Go
Raw Normal View History

2022-10-13 03:09:52 +00:00
package middleware
import (
"github.com/gin-gonic/gin"
"net/http"
"sync"
"sync/atomic"
)
2025-03-16 14:11:28 +00:00
type ipLimitMap struct {
2022-10-14 09:15:43 +00:00
mux *sync.RWMutex
2022-10-13 03:09:52 +00:00
m map[string]*int64
2022-11-16 03:09:25 +00:00
limitNum *int64
2025-03-16 14:11:28 +00:00
clearNum *int64
2022-10-13 03:09:52 +00:00
}
2025-03-16 14:11:28 +00:00
func IpLimit(num int64, clearNum ...int64) (func(ctx *gin.Context), func(int64, ...int64)) {
m := ipLimitMap{
2022-10-14 09:15:43 +00:00
mux: &sync.RWMutex{},
2022-10-13 03:09:52 +00:00
m: make(map[string]*int64),
2022-11-16 03:09:25 +00:00
limitNum: new(int64),
2025-03-16 14:11:28 +00:00
clearNum: new(int64),
2022-10-13 03:09:52 +00:00
}
2025-03-16 14:11:28 +00:00
fn := func(num int64, clearNum ...int64) {
2022-11-16 03:09:25 +00:00
atomic.StoreInt64(m.limitNum, num)
2025-03-16 14:11:28 +00:00
if len(clearNum) > 0 {
atomic.StoreInt64(m.clearNum, clearNum[0])
}
2022-11-16 03:09:25 +00:00
}
2025-03-16 14:11:28 +00:00
fn(num, clearNum...)
2022-10-13 03:09:52 +00:00
return func(c *gin.Context) {
if atomic.LoadInt64(m.limitNum) <= 0 {
c.Next()
return
}
2022-10-13 03:09:52 +00:00
ip := c.ClientIP()
2022-10-14 09:15:43 +00:00
m.mux.RLock()
i, ok := m.m[ip]
m.mux.RUnlock()
if !ok {
m.mux.Lock()
i = new(int64)
m.m[ip] = i
m.mux.Unlock()
}
2022-10-13 03:09:52 +00:00
defer func() {
2025-03-16 14:11:28 +00:00
atomic.AddInt64(i, -1)
if atomic.LoadInt64(i) <= 0 {
cNum := int(atomic.LoadInt64(m.clearNum))
if cNum <= 0 {
m.mux.Lock()
delete(m.m, ip)
m.mux.Unlock()
return
}
m.mux.RLock()
l := len(m.m)
m.mux.RUnlock()
if l < cNum {
2022-10-13 03:09:52 +00:00
m.mux.Lock()
delete(m.m, ip)
m.mux.Unlock()
}
}
}()
2022-10-14 09:15:43 +00:00
if atomic.LoadInt64(i) >= atomic.LoadInt64(m.limitNum) {
2025-03-16 14:11:28 +00:00
c.String(http.StatusForbidden, "请求太多了,服务器君表示压力山大==!, 请稍后访问")
2022-10-13 03:09:52 +00:00
c.Abort()
return
}
atomic.AddInt64(i, 1)
2022-10-14 09:15:43 +00:00
c.Next()
2022-11-16 03:09:25 +00:00
}, fn
2022-10-13 03:09:52 +00:00
}