diff --git a/src/gateway/mod.rs b/src/gateway/mod.rs index deba8ff..039139b 100644 --- a/src/gateway/mod.rs +++ b/src/gateway/mod.rs @@ -23,7 +23,9 @@ use axum::{ }; use std::net::SocketAddr; use std::sync::Arc; +use std::time::Duration; use tower_http::limit::RequestBodyLimitLayer; +use tower_http::timeout::TimeoutLayer; /// Maximum request body size (64KB) — prevents memory exhaustion pub const MAX_BODY_SIZE: usize = 65_536; @@ -163,8 +165,6 @@ pub async fn run_gateway(host: &str, port: u16, config: Config) -> Result<()> { }; // Build router with middleware - // Note: Body limit layer prevents memory exhaustion from oversized requests - // Timeout is handled by tokio's TcpListener accept timeout and hyper's built-in timeouts let app = Router::new() .route("/health", get(handle_health)) .route("/pair", post(handle_pair)) @@ -172,7 +172,11 @@ pub async fn run_gateway(host: &str, port: u16, config: Config) -> Result<()> { .route("/whatsapp", get(handle_whatsapp_verify)) .route("/whatsapp", post(handle_whatsapp_message)) .with_state(state) - .layer(RequestBodyLimitLayer::new(MAX_BODY_SIZE)); + .layer(RequestBodyLimitLayer::new(MAX_BODY_SIZE)) + .layer(TimeoutLayer::with_status_code( + StatusCode::REQUEST_TIMEOUT, + Duration::from_secs(REQUEST_TIMEOUT_SECS), + )); // Run the server axum::serve(listener, app).await?; diff --git a/src/security/secrets.rs b/src/security/secrets.rs index bafad38..3940843 100644 --- a/src/security/secrets.rs +++ b/src/security/secrets.rs @@ -241,7 +241,7 @@ fn hex_encode(data: &[u8]) -> String { /// Hex-decode a hex string to bytes. fn hex_decode(hex: &str) -> Result> { - if hex.len() % 2 != 0 { + if !hex.len().is_multiple_of(2) { anyhow::bail!("Hex string has odd length"); } (0..hex.len()) diff --git a/src/tools/browser.rs b/src/tools/browser.rs index 5ee9505..25be13c 100644 --- a/src/tools/browser.rs +++ b/src/tools/browser.rs @@ -366,6 +366,7 @@ impl BrowserTool { } #[async_trait] +#[allow(clippy::too_many_lines)] impl Tool for BrowserTool { fn name(&self) -> &str { "browser"