我使用 Go 开发了一个 HTTP 服务器。现在我想实现一个速率限制器,这样我就可以检查来自特定 IP 的 HTTP 请求是否在 1 分钟内发送超过 10 个 HTTP 请求,我可以将该 IP 放入阻止列表中一段时间,比如(1 小时) 并且与此同时,同一订阅者在他/她处于阻塞期时正在发送请求,我将从 HTTP 服务器发送 429 错误响应。
我为此编写了一个代码,但在此能够阻止 IP 地址,但它会在 1 小时后解除对所有 IP 的阻止。我期待先到先解锁。
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
}
HUWWW
qq_花开花谢_0
相关分类