Check rate limits
(&self, client_ip: Option<IpAddr>)
| 512 | |
| 513 | /// Check rate limits |
| 514 | fn check_rate_limits(&self, client_ip: Option<IpAddr>) -> Result<(), RateLimitError> { |
| 515 | // If per-IP limiting is enabled and we have an IP, check per-IP limits |
| 516 | if self.rate_config.per_ip_limiting { |
| 517 | if let Some(ip) = client_ip { |
| 518 | let mut ip_windows = self.ip_windows.write(); |
| 519 | |
| 520 | // Check if we're tracking too many IPs |
| 521 | if ip_windows.len() >= self.rate_config.max_tracked_ips && !ip_windows.contains_key(&ip) { |
| 522 | warn!("Too many IP addresses being tracked, falling back to global rate limiting for {}", ip); |
| 523 | // Fall through to global rate limiting |
| 524 | } else { |
| 525 | let window = ip_windows.entry(ip).or_insert_with(RateLimitWindow::new); |
| 526 | |
| 527 | let (requests, _was_reset) = window.check_and_increment(self.rate_config.window_duration); |
| 528 | if requests > self.rate_config.max_requests { |
| 529 | // Log rate limit exceeded event |
| 530 | events::rate_limit_exceeded(Some(ip), "per-ip", requests); |
| 531 | |
| 532 | return Err(RateLimitError::RateLimitExceeded( |
| 533 | format!("Per-IP rate limit exceeded for {}: {} requests per {} seconds", |
| 534 | ip, |
| 535 | self.rate_config.max_requests, |
| 536 | self.rate_config.window_duration.as_secs()) |
| 537 | )); |
| 538 | } |
| 539 | |
| 540 | // Per-IP limit passed, no need to check global limit |
| 541 | return Ok(()); |
| 542 | } |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | // Check global rate limit (only if per-IP limiting is disabled or IP tracking is full) |
| 547 | { |
| 548 | let global_window = self.global_window.read(); |
| 549 | let (requests, _was_reset) = global_window.check_and_increment(self.rate_config.window_duration); |
| 550 | if requests > self.rate_config.max_requests { |
| 551 | // Log rate limit exceeded event |
| 552 | events::rate_limit_exceeded(client_ip, "global", requests); |
| 553 | |
| 554 | return Err(RateLimitError::RateLimitExceeded( |
| 555 | format!("Global rate limit exceeded: {} requests per {} seconds", |
| 556 | self.rate_config.max_requests, |
| 557 | self.rate_config.window_duration.as_secs()) |
| 558 | )); |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | Ok(()) |
| 563 | } |
| 564 | |
| 565 | /// Clean up expired rate limit windows |
| 566 | fn maybe_cleanup(&self) { |
no test coverage detected