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
This commit is contained in:
2026-01-26 11:04:14 +00:00
parent 1152308f6c
commit da219dc794
2 changed files with 18 additions and 10 deletions

View File

@@ -219,14 +219,22 @@ async fn run_server(config: Config, storage: Storage) {
.merge(registry::pypi_routes()) .merge(registry::pypi_routes())
.layer(rate_limit::upload_rate_limiter()); .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(health::routes())
.merge(metrics::routes()) .merge(metrics::routes())
.merge(ui::routes()) .merge(ui::routes())
.merge(openapi::routes()) .merge(openapi::routes());
// Routes WITH rate limiting
let rate_limited_routes = Router::new()
.merge(auth_routes) .merge(auth_routes)
.merge(registry_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(DefaultBodyLimit::max(100 * 1024 * 1024)) // 100MB default body limit
.layer(middleware::from_fn(request_id::request_id_middleware)) .layer(middleware::from_fn(request_id::request_id_middleware))
.layer(middleware::from_fn(metrics::metrics_middleware)) .layer(middleware::from_fn(metrics::metrics_middleware))

View File

@@ -30,8 +30,8 @@ impl Default for RateLimitConfig {
Self { Self {
auth_rps: 1, // 1 req/sec for auth (strict) auth_rps: 1, // 1 req/sec for auth (strict)
auth_burst: 5, // Allow burst of 5 auth_burst: 5, // Allow burst of 5
upload_rps: 50, // 50 req/sec for uploads (Docker needs parallel) upload_rps: 200, // 200 req/sec for uploads (Docker needs high parallelism)
upload_burst: 100, // Allow burst of 100 upload_burst: 500, // Allow burst of 500
general_rps: 100, // 100 req/sec general general_rps: 100, // 100 req/sec general
general_burst: 200, // Allow burst of 200 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 /// Create rate limiter layer for upload endpoints
/// ///
/// Default: 50 requests per second, burst of 100 /// Default: 200 requests per second, burst of 500
/// Higher limits to accommodate Docker client's parallel layer uploads /// High limits to accommodate Docker client's aggressive parallel layer uploads
pub fn upload_rate_limiter() -> tower_governor::GovernorLayer< pub fn upload_rate_limiter() -> tower_governor::GovernorLayer<
tower_governor::key_extractor::PeerIpKeyExtractor, tower_governor::key_extractor::PeerIpKeyExtractor,
governor::middleware::StateInformationMiddleware, governor::middleware::StateInformationMiddleware,
axum::body::Body, axum::body::Body,
> { > {
let config = GovernorConfigBuilder::default() let config = GovernorConfigBuilder::default()
.per_second(50) .per_second(200)
.burst_size(100) .burst_size(500)
.use_headers() .use_headers()
.finish() .finish()
.unwrap(); .unwrap();
@@ -102,7 +102,7 @@ mod tests {
let config = RateLimitConfig::default(); let config = RateLimitConfig::default();
assert_eq!(config.auth_rps, 1); assert_eq!(config.auth_rps, 1);
assert_eq!(config.auth_burst, 5); assert_eq!(config.auth_burst, 5);
assert_eq!(config.upload_rps, 50); assert_eq!(config.upload_rps, 200);
assert_eq!(config.general_rps, 100); assert_eq!(config.general_rps, 100);
} }