Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more changes #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions limit.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
package antiDdos

import (
"net"
"net/http"
"strings"
"sync"
"time"

"golang.org/x/time/rate"
)

// r - time.second
// b - request/per time

// IPRateLimiter представляет собой ограничитель скорости по IP-адресу.
type IPRateLimiter struct {
ips map[string]*rate.Limiter
mu *sync.RWMutex
r rate.Limit
b int
ips map[string]*rate.Limiter // Карта IP-адресов и соответствующих ограничителей скорости
mu *sync.RWMutex // Мьютекс для безопасного доступа к картам IP-адресов
r rate.Limit // Предел скорости
b int // Максимальное количество запросов, разрешенных в интервал времени
}

// NewIPRateLimiter создает новый экземпляр IPRateLimiter с заданным интервалом времени и максимальным количеством запросов.
func NewIPRateLimiter(t time.Duration, b int) *IPRateLimiter {
i := &IPRateLimiter{
ips: make(map[string]*rate.Limiter),
Expand All @@ -30,6 +29,7 @@ func NewIPRateLimiter(t time.Duration, b int) *IPRateLimiter {
return i
}

// AddIP добавляет IP-адрес в карту IP-адресов и создает для него новый ограничитель скорости.
func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
i.mu.Lock()
defer i.mu.Unlock()
Expand All @@ -41,24 +41,35 @@ func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
return limiter
}

// GetLimiter возвращает ограничитель скорости для заданного IP-адреса.
// Если ограничитель для данного IP-адреса уже существует, он возвращается.
// В противном случае создается новый ограничитель и добавляется в карту IP-адресов.
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
i.mu.Lock()
defer i.mu.Unlock()

limiter, exists := i.ips[ip]

if !exists {
i.mu.Unlock()
return i.AddIP(ip)
limiter = i.AddIP(ip)
}

i.mu.Unlock()

return limiter
}


func (i *IPRateLimiter) LimitMiddleware(next http.Handler) http.Handler {
// LimitMiddleware является промежуточным обработчиком HTTP и ограничивает скорость запросов для каждого IP-адреса.
// Если количество запросов превышает максимальное количество разрешенных запросов в заданный интервал времени,
// возвращается ошибка "Too Many Requests" (код 429).
func (i *IPRateLimiter) LimitMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
limiter := i.GetLimiter(getIPFromRemoteAddr(r.RemoteAddr))
ip := getClientIP(r)

if ip == "" {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}

limiter := i.GetLimiter(ip)

if !limiter.Allow() {
http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
Expand All @@ -69,8 +80,14 @@ func (i *IPRateLimiter) LimitMiddleware(next http.Handler) http.Handler {
})
}

func getIPFromRemoteAddr(remoteAddr string) (ip string) {
trim := strings.Split(remoteAddr, ":")
ip = trim[0]
return
}
// getClientIP возвращает IP-адрес клиента из заголовка X-Forwarded-For
// Если заголовок отсутствует, то IP-адрес извлекается из RemoteAddr.
func getClientIP(r *http.Request) string {
ip := r.Header.Get("X-Forwarded-For")

if ip == "" {
ip, _, _ = net.SplitHostPort(r.RemoteAddr)
}

return ip
}