|
|
@@ -5,12 +5,12 @@ import (
|
|
|
"context"
|
|
|
"net/http"
|
|
|
"strconv"
|
|
|
+ "strings"
|
|
|
"time"
|
|
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
|
"github.com/ulule/limiter/v3"
|
|
|
limiterRedis "github.com/ulule/limiter/v3/drivers/store/redis"
|
|
|
- chimiddleware "github.com/go-chi/chi/v5/middleware"
|
|
|
)
|
|
|
|
|
|
type RedisRateLimiter struct {
|
|
|
@@ -74,8 +74,21 @@ func writeRateLimitError(w http.ResponseWriter, reset int64) {
|
|
|
_, _ = w.Write([]byte(`{"error":"rate limit exceeded"}`))
|
|
|
}
|
|
|
|
|
|
+// GetClientIP извлекает реальный IP клиента из заголовков X-Forwarded-For,
|
|
|
+// X-Real-IP или RemoteAddr. Используется для ключей rate limiter по IP.
|
|
|
func GetClientIP(r *http.Request) string {
|
|
|
- return chimiddleware.GetIP(r)
|
|
|
+ if fwd := r.Header.Get("X-Forwarded-For"); fwd != "" {
|
|
|
+ parts := strings.Split(fwd, ",")
|
|
|
+ return strings.TrimSpace(parts[0])
|
|
|
+ }
|
|
|
+ if realIP := r.Header.Get("X-Real-IP"); realIP != "" {
|
|
|
+ return realIP
|
|
|
+ }
|
|
|
+ addr := r.RemoteAddr
|
|
|
+ if idx := strings.LastIndex(addr, ":"); idx != -1 {
|
|
|
+ return addr[:idx]
|
|
|
+ }
|
|
|
+ return addr
|
|
|
}
|
|
|
|
|
|
func KeyByIP(prefix string) func(*http.Request) string {
|