BREAKING CHANGE(ts-api,rustproxy): remove deprecated TypeScript protocol and utility exports while hardening QUIC, HTTP/3, WebSocket, and rate limiter cleanup paths

This commit is contained in:
2026-03-21 22:23:38 +00:00
parent 33fdf42a70
commit fc04a0210b
78 changed files with 331 additions and 10754 deletions

View File

@@ -203,6 +203,10 @@ pub struct HttpProxyService {
route_rate_limiters: Arc<DashMap<String, Arc<RateLimiter>>>,
/// Request counter for periodic rate limiter cleanup.
request_counter: AtomicU64,
/// Epoch for time-based rate limiter cleanup.
rate_limiter_epoch: std::time::Instant,
/// Last rate limiter cleanup time (ms since epoch).
last_rate_limiter_cleanup_ms: AtomicU64,
/// Cache of compiled URL rewrite regexes (keyed by pattern string).
regex_cache: DashMap<String, Regex>,
/// Shared backend TLS config for session resumption across connections.
@@ -233,6 +237,8 @@ impl HttpProxyService {
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
route_rate_limiters: Arc::new(DashMap::new()),
request_counter: AtomicU64::new(0),
rate_limiter_epoch: std::time::Instant::now(),
last_rate_limiter_cleanup_ms: AtomicU64::new(0),
regex_cache: DashMap::new(),
backend_tls_config: Self::default_backend_tls_config(),
backend_tls_config_alpn: Self::default_backend_tls_config_with_alpn(),
@@ -258,6 +264,8 @@ impl HttpProxyService {
connect_timeout,
route_rate_limiters: Arc::new(DashMap::new()),
request_counter: AtomicU64::new(0),
rate_limiter_epoch: std::time::Instant::now(),
last_rate_limiter_cleanup_ms: AtomicU64::new(0),
regex_cache: DashMap::new(),
backend_tls_config: Self::default_backend_tls_config(),
backend_tls_config_alpn: Self::default_backend_tls_config_with_alpn(),
@@ -524,9 +532,13 @@ impl HttpProxyService {
}
}
// Periodic rate limiter cleanup (every 1000 requests)
// Periodic rate limiter cleanup (every 1000 requests or every 60s)
let count = self.request_counter.fetch_add(1, Ordering::Relaxed);
if count % 1000 == 0 {
let now_ms = self.rate_limiter_epoch.elapsed().as_millis() as u64;
let last_cleanup = self.last_rate_limiter_cleanup_ms.load(Ordering::Relaxed);
let time_triggered = now_ms.saturating_sub(last_cleanup) >= 60_000;
if count % 1000 == 0 || time_triggered {
self.last_rate_limiter_cleanup_ms.store(now_ms, Ordering::Relaxed);
for entry in self.route_rate_limiters.iter() {
entry.value().cleanup();
}
@@ -2134,12 +2146,26 @@ impl HttpProxyService {
let ws_max_lifetime = self.ws_max_lifetime;
tokio::spawn(async move {
// RAII guard: ensures connection_ended is called even if this task panics
struct WsUpstreamGuard {
selector: UpstreamSelector,
key: String,
}
impl Drop for WsUpstreamGuard {
fn drop(&mut self) {
self.selector.connection_ended(&self.key);
}
}
let _upstream_guard = WsUpstreamGuard {
selector: upstream_selector,
key: upstream_key_owned.clone(),
};
let client_upgraded = match on_client_upgrade.await {
Ok(upgraded) => upgraded,
Err(e) => {
debug!("WebSocket: client upgrade failed: {}", e);
upstream_selector.connection_ended(&upstream_key_owned);
return;
return; // _upstream_guard Drop handles connection_ended
}
};
@@ -2298,9 +2324,7 @@ impl HttpProxyService {
watchdog.abort();
debug!("WebSocket tunnel closed: {} bytes in, {} bytes out", bytes_in, bytes_out);
upstream_selector.connection_ended(&upstream_key_owned);
// Bytes already reported per-chunk in the copy loops above
// _upstream_guard Drop handles connection_ended on all paths including panic
});
let body: BoxBody<Bytes, hyper::Error> = BoxBody::new(
@@ -2822,6 +2846,8 @@ impl Default for HttpProxyService {
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
route_rate_limiters: Arc::new(DashMap::new()),
request_counter: AtomicU64::new(0),
rate_limiter_epoch: std::time::Instant::now(),
last_rate_limiter_cleanup_ms: AtomicU64::new(0),
regex_cache: DashMap::new(),
backend_tls_config: Self::default_backend_tls_config(),
backend_tls_config_alpn: Self::default_backend_tls_config_with_alpn(),