Rate Limiter Http Di Golang
Yang Ingin Membantu Saya Untuk Terus Berkontribusi Boleh Banget Klik Dibawah
package middleware
import (
"log"
"net"
"net/http"
"sync"
"time"
"golang.org/x/time/rate"
)
// getVisitor
type visitor struct {
limiter *rate.Limiter
lastSeen time.Time
}
var visitors = make(map[string]*visitor)
var mu sync.Mutex
// menjalankan di belakang clean up visitor
func init() {
go cleanupVisitors()
}
// membersihkan map visitor ketika sudah tiga menit
func cleanupVisitors() {
for {
time.Sleep(time.Minute)
mu.Lock()
for ip, v := range visitors {
if time.Since(v.lastSeen) > 3*time.Minute {
delete(visitors, ip)
}
}
mu.Unlock()
}
}
// menangkap semua pengunjung berdasarkan ip yang melakukan request
func getVisitor(ip string) *rate.Limiter {
mu.Lock()
defer mu.Unlock()
v, exists := visitors[ip]
// mengecheck apakah ip ini ada
// jika tidak ada daftarkan ipnya di map
if !exists {
// setiap satu detik hanya ada 15 request yang diperbolahkan
limiter := rate.NewLimiter(1, 15)
// menyimpan ip dan menetapkan limiter
visitors[ip] = &visitor{limiter, time.Now()}
return limiter
}
// ketika ip ditemukan jalankan limiter dari ip itu
// Update waktu terakhir dia request
v.lastSeen = time.Now()
return v.limiter
}
// ini bisa di gunakan nanti sebagai middleware
func Limiter(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var host, _, err = net.SplitHostPort(r.RemoteAddr)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// check visitor
var limiter = getVisitor(host)
// jika limit penuh return error to many request
if !limiter.Allow() {
http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
return
}
h.ServeHTTP(w, r)
})
}

Last updated


