From da219dc79471763a8bde7eb980aeb01159571386 Mon Sep 17 00:00:00 2001 From: DevITWay Date: Mon, 26 Jan 2026 11:04:14 +0000 Subject: [PATCH] Fix rate limiting: exempt health/metrics, increase upload limits - Health, metrics, UI, and API docs are now exempt from rate limiting - Increased upload rate limits to 200 req/s with burst of 500 for Docker compatibility --- nora-registry/src/main.rs | 14 +++++++++++--- nora-registry/src/rate_limit.rs | 14 +++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/nora-registry/src/main.rs b/nora-registry/src/main.rs index 796bde5..4a5d0af 100644 --- a/nora-registry/src/main.rs +++ b/nora-registry/src/main.rs @@ -219,14 +219,22 @@ async fn run_server(config: Config, storage: Storage) { .merge(registry::pypi_routes()) .layer(rate_limit::upload_rate_limiter()); - let app = Router::new() + // Routes WITHOUT rate limiting (health, metrics, UI) + let public_routes = Router::new() .merge(health::routes()) .merge(metrics::routes()) .merge(ui::routes()) - .merge(openapi::routes()) + .merge(openapi::routes()); + + // Routes WITH rate limiting + let rate_limited_routes = Router::new() .merge(auth_routes) .merge(registry_routes) - .layer(rate_limit::general_rate_limiter()) // General rate limit for all routes + .layer(rate_limit::general_rate_limiter()); + + let app = Router::new() + .merge(public_routes) + .merge(rate_limited_routes) .layer(DefaultBodyLimit::max(100 * 1024 * 1024)) // 100MB default body limit .layer(middleware::from_fn(request_id::request_id_middleware)) .layer(middleware::from_fn(metrics::metrics_middleware)) diff --git a/nora-registry/src/rate_limit.rs b/nora-registry/src/rate_limit.rs index 12fe21e..2c6bbea 100644 --- a/nora-registry/src/rate_limit.rs +++ b/nora-registry/src/rate_limit.rs @@ -30,8 +30,8 @@ impl Default for RateLimitConfig { Self { auth_rps: 1, // 1 req/sec for auth (strict) auth_burst: 5, // Allow burst of 5 - upload_rps: 50, // 50 req/sec for uploads (Docker needs parallel) - upload_burst: 100, // Allow burst of 100 + upload_rps: 200, // 200 req/sec for uploads (Docker needs high parallelism) + upload_burst: 500, // Allow burst of 500 general_rps: 100, // 100 req/sec general general_burst: 200, // Allow burst of 200 } @@ -58,16 +58,16 @@ pub fn auth_rate_limiter() -> tower_governor::GovernorLayer< /// Create rate limiter layer for upload endpoints /// -/// Default: 50 requests per second, burst of 100 -/// Higher limits to accommodate Docker client's parallel layer uploads +/// Default: 200 requests per second, burst of 500 +/// High limits to accommodate Docker client's aggressive parallel layer uploads pub fn upload_rate_limiter() -> tower_governor::GovernorLayer< tower_governor::key_extractor::PeerIpKeyExtractor, governor::middleware::StateInformationMiddleware, axum::body::Body, > { let config = GovernorConfigBuilder::default() - .per_second(50) - .burst_size(100) + .per_second(200) + .burst_size(500) .use_headers() .finish() .unwrap(); @@ -102,7 +102,7 @@ mod tests { let config = RateLimitConfig::default(); assert_eq!(config.auth_rps, 1); assert_eq!(config.auth_burst, 5); - assert_eq!(config.upload_rps, 50); + assert_eq!(config.upload_rps, 200); assert_eq!(config.general_rps, 100); }