getClientIP extracts the client IP from the request, handling proxy headers
(r *http.Request)
| 3243 | |
| 3244 | // getClientIP extracts the client IP from the request, handling proxy headers |
| 3245 | func getClientIP(r *http.Request) string { |
| 3246 | // Check X-Forwarded-For header first (for reverse proxies) |
| 3247 | xff := r.Header.Get("X-Forwarded-For") |
| 3248 | if xff != "" { |
| 3249 | // Take the first IP in the chain |
| 3250 | ips := strings.Split(xff, ",") |
| 3251 | if len(ips) > 0 { |
| 3252 | ip := strings.TrimSpace(ips[0]) |
| 3253 | if net.ParseIP(ip) != nil { |
| 3254 | return ip |
| 3255 | } |
| 3256 | } |
| 3257 | } |
| 3258 | |
| 3259 | // Check X-Real-IP header |
| 3260 | xri := r.Header.Get("X-Real-IP") |
| 3261 | if xri != "" { |
| 3262 | ip := strings.TrimSpace(xri) |
| 3263 | if net.ParseIP(ip) != nil { |
| 3264 | return ip |
| 3265 | } |
| 3266 | } |
| 3267 | |
| 3268 | // Fall back to RemoteAddr |
| 3269 | host, _, err := net.SplitHostPort(r.RemoteAddr) |
| 3270 | if err != nil { |
| 3271 | return r.RemoteAddr |
| 3272 | } |
| 3273 | return host |
| 3274 | } |
| 3275 | |
| 3276 | // Global rate limiter instance |
| 3277 | var authRateLimiter = NewRateLimiter() |
no test coverage detected