Я разработал HTTP-сервер, используя Go. Теперь я хотел бы реализовать ограничитель скорости, чтобы я мог проверить, отправляет ли HTTP-запрос с определенного IP-адреса более 10 HTTP-запросов за 1 минуту, и я могу поместить этот IP-адрес в черный список на некоторое время, скажем (1 час ) и в то же время тот же подписчик отправляет запросы, когда он / она находился в периоде блокировки. Я отправляю сообщение об ошибке 429 с HTTP-сервера.
Я написал код для этого, но в этом состоянии заблокировать IP-адреса, но при этом разблокировать все IP-адреса через 1 час времени. Я ожидаю, что сначала придет первым разблокировать.
Package main
import (
"log"
"net/http"
"strings"
"time"
)
func main() {
fs := http.FileServer(http.Dir("./html/"))
http.Handle("/", fs)
log.Println("Listening..")
go clearLastRequestsIPs()
go clearBlockedIPs()
err := http.ListenAndServe(":8080", middleware(nil))
if err != nil {
log.Fatalln(err)
}
}
// Stores last requests IPs
var lastRequestsIPs []string
// Block IP for 1 hours
var blockedIPs []string
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
if existsBlockedIP(ipAddr) {
http.Error(w, "", http.StatusTooManyRequests)
return
}
// how many requests the current IP made in last 5 mins
requestCounter := 0
for _, ip := range lastRequestsIPs {
if ip == ipAddr {
requestCounter++
}
}
if requestCounter >= 1000 {
blockedIPs = append(blockedIPs, ipAddr)
http.Error(w, "", http.StatusTooManyRequests)
return
}
lastRequestsIPs = append(lastRequestsIPs, ipAddr)
if next == nil {
http.DefaultServeMux.ServeHTTP(w, r)
return
}
next.ServeHTTP(w, r)
})
}
func existsBlockedIP(ipAddr string) bool {
for _, ip := range blockedIPs {
if ip == ipAddr {
return true
}
}
return false
}
func existsLastRequest(ipAddr string) bool {
for _, ip := range lastRequestsIPs {
if ip == ipAddr {
return true
}
}
return false
}
// Clears lastRequestsIPs array every 1 hrs
func clearLastRequestsIPs() {
for {
lastRequestsIPs = []string{}
time.Sleep(time.Hour * 1)
}
}
// Clears blockedIPs array every 1 hours
func clearBlockedIPs() {
for {
blockedIPs = []string{}
time.Sleep(time.Hour * 1)
}
}