From 9bd74f46805e06e152339a5a9502ba2cdffb54b3 Mon Sep 17 00:00:00 2001 From: Ansaf Ahmed Date: Mon, 20 Apr 2026 15:05:00 +1000 Subject: [PATCH 1/2] update: add the ability for manual invalidation of requests, preventing underlying connection from being reused in custom pool implementations. --- src/http/mod.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/http/mod.rs b/src/http/mod.rs index 5db1c28..8e8f6f1 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -259,7 +259,7 @@ impl ConnectionPool for SingleTlsConnectionPool { fn release(&mut self, conn: Option>) { self.has_active_connection = false; if let Some(conn) = conn { - if !conn.disconnected { + if conn.is_reusable() { let _ = self.conn.insert(conn); } } @@ -346,6 +346,30 @@ impl, const CHUNK_SIZE: usize> HttpRequest bool { + self.conn.as_ref().map_or(false, |c| c.invalidated) + } + + /// Returns `true` if the connection can be reused by the pool. + /// + /// A connection is reusable if it is neither disconnected (IO error) + /// nor invalidated (user-requested). + #[inline] + pub fn is_reusable(&self) -> bool { + self.conn.as_ref().map_or(false, |c| c.is_reusable()) + } + /// Read from the stream and return when complete. Must provide buffer that will hold the response. /// It's ok to re-use the buffer as long as it's been cleared before using it with a new request. /// @@ -464,6 +488,7 @@ pub struct Connection { stream: S, buffer: Vec, disconnected: bool, + invalidated: bool, header_finder: Finder, } @@ -526,6 +551,7 @@ impl Connection { stream, buffer: Vec::with_capacity(CHUNK_SIZE), disconnected: false, + invalidated: false, header_finder: Finder::new(b"\r\n\r\n"), } } @@ -535,6 +561,21 @@ impl Connection { pub const fn is_disconnected(&self) -> bool { self.disconnected } + + /// Returns whether the connection has been explicitly invalidated by the user. + #[inline] + pub const fn is_invalidated(&self) -> bool { + self.invalidated + } + + /// Returns whether this connection can be reused by the pool. + /// + /// A connection is reusable if it is neither disconnected (IO error) + /// nor invalidated (user-requested). + #[inline] + pub const fn is_reusable(&self) -> bool { + !self.disconnected && !self.invalidated + } } #[cfg(test)] From f9ff5d76b1e97f2e3fcd78b6c4a744dc78500d00 Mon Sep 17 00:00:00 2001 From: Ansaf Ahmed Date: Mon, 20 Apr 2026 15:13:38 +1000 Subject: [PATCH 2/2] fix: clippy errors --- src/http/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/http/mod.rs b/src/http/mod.rs index 8e8f6f1..749a79c 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -358,7 +358,7 @@ impl, const CHUNK_SIZE: usize> HttpRequest bool { - self.conn.as_ref().map_or(false, |c| c.invalidated) + self.conn.as_ref().is_some_and(|c| c.invalidated) } /// Returns `true` if the connection can be reused by the pool. @@ -367,7 +367,7 @@ impl, const CHUNK_SIZE: usize> HttpRequest bool { - self.conn.as_ref().map_or(false, |c| c.is_reusable()) + self.conn.as_ref().is_some_and(|c| c.is_reusable()) } /// Read from the stream and return when complete. Must provide buffer that will hold the response.