亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

基于主機地址的限速http請求

基于主機地址的限速http請求

Go
aluckdog 2022-05-18 14:43:36
我使用 Go 開發了一個 HTTP 服務器?,F在我想實現一個速率限制器,這樣我就可以檢查來自特定 IP 的 HTTP 請求是否在 1 分鐘內發送超過 10 個 HTTP 請求,我可以將該 IP 放入阻止列表中一段時間,比如(1 小時) 并且與此同時,同一訂閱者在他/她處于阻塞期時正在發送請求,我將從 HTTP 服務器發送 429 錯誤響應。我為此編寫了一個代碼,但在此能夠阻止 IP 地址,但它會在 1 小時后解除對所有 IP 的阻止。我期待先到先解鎖。Package mainimport (    "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 IPsvar lastRequestsIPs []string// Block IP for 1 hoursvar blockedIPs []stringfunc 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}
查看完整描述

2 回答

?
HUWWW

TA貢獻1874條經驗 獲得超12個贊

你可以使用一些像這樣的中間件:


type Limiter struct {

    ipCount map[string]int

    sync.Mutex

}


var limiter Limiter

func init() {

    limiter.ipCount = make(map[string]int)

}


func limit(next http.Handler) http.Handler {

  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

    // Get the IP address for the current user.

    ip, _, err := net.SplitHostPort(r.RemoteAddr)

    if err != nil {

      log.Println(err.Error())

      http.Error(w, "Internal Server Error", http.StatusInternalServerError)

      return

    }


    // Get the # of times the visitor has visited in the last 60 seconds

    limiter.Lock()

    count, ok := limiter.ipCount[ip]

    if !ok {

        limiter.ipCount[ip] = 0

    }

    if count > 10 {

      limiter.Unlock()

      http.Error(w, http.StatusText(429), http.StatusTooManyRequests)

      return

    } else {

        limiter.ipCount[ip]++

    }

    time.AfterFunc(time.Second * 60, func() {

        limiter.Lock()

        limiter.ipCount[ip]--

        limiter.Unlock()

    })

    if limiter.ipCount[ip] == 10 {

        // set it to 20 so the decrement timers will only decrease it to

        // 10, and they stay blocked until the next timer resets it to 0

        limiter.ipCount[ip] = 20

        time.AfterFunc(time.Hour, func() {

            limiter.Lock()

            limiter.ipCount[ip] = 0

            limiter.Unlock()

        })

    }

    limiter.Unlock()

    next.ServeHTTP(w, r)

  })

}    



查看完整回答
反對 回復 2022-05-18
?
qq_花開花謝_0

TA貢獻1835條經驗 獲得超7個贊

rate.NewLimiter()從 golang.org/x/time/rate 包中使用。



查看完整回答
反對 回復 2022-05-18
  • 2 回答
  • 0 關注
  • 137 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號