wp-go/middleware/iplimit.go

58 lines
921 B
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"
)
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
limitNum int64
}
func IpLimit(num int64) func(ctx *gin.Context) {
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),
limitNum: num,
}
return func(c *gin.Context) {
ip := c.ClientIP()
s := false
2022-10-14 09:15:43 +00:00
m.mux.RLock()
i, ok := m.m[ip]
m.mux.RUnlock()
2022-10-13 03:09:52 +00:00
defer func() {
2022-10-14 09:15:43 +00:00
ii := atomic.LoadInt64(i)
if s && ii > 0 {
2022-10-13 03:09:52 +00:00
atomic.AddInt64(i, -1)
2022-10-14 09:15:43 +00:00
if atomic.LoadInt64(i) == 0 {
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
2022-10-13 03:09:52 +00:00
if !ok {
m.mux.Lock()
i = new(int64)
m.m[ip] = i
m.mux.Unlock()
}
2022-10-14 09:15:43 +00:00
if m.limitNum > 0 && atomic.LoadInt64(i) >= m.limitNum {
2022-10-13 03:09:52 +00:00
c.Status(http.StatusForbidden)
c.Abort()
return
}
atomic.AddInt64(i, 1)
2022-10-14 09:15:43 +00:00
s = true
c.Next()
2022-10-13 03:09:52 +00:00
}
}