Add scheme to PoolKey and let port be None. (#84)

PoolKey calls unwrap() on an option that can be None. Specifically, the
local variable `port` can be None when PoolKey is constructed with a Url
whose scheme is unrecognized in url.port_or_known_default().

To fix that, make port an Option. Also, make scheme part of the PoolKey.
This prevents, for instance, a stream opened for `https://example.com:9999`
being reused on a request for `http://example.com:9999`.

Remove the test-only pool.get() accessor. This was used in only one test,
agent_pool in range.rs. This seemed like it was testing the agent more
than it was testing ranges, so I moved it to agent.rs and edited to
remove the range-testing parts.

Also, reject unrecognized URLs earlier in connect_socket so they don't
reach try_get_connection.
This commit is contained in:
Jacob Hoffman-Andrews
2020-06-22 23:23:39 -07:00
committed by GitHub
parent 00461fb5bd
commit 3014f58a28
4 changed files with 46 additions and 61 deletions

View File

@@ -33,43 +33,32 @@ impl ConnectionPool {
pub fn len(&self) -> usize {
self.recycle.len()
}
#[cfg(all(test, any(feature = "tls", feature = "native-tls")))]
pub fn get(&self, hostname: &str, port: u16) -> Option<&Stream> {
let key = PoolKey {
hostname: hostname.into(),
port,
};
self.recycle.get(&key)
}
}
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
struct PoolKey {
scheme: String,
hostname: String,
port: u16,
port: Option<u16>,
}
impl PoolKey {
fn new(url: &Url) -> Self {
let port = if cfg!(test) {
if let Some(p) = url.port_or_known_default() {
Some(p)
} else if url.scheme() == "test" {
Some(42)
} else {
None
}
} else {
url.port_or_known_default()
};
let port = url.port_or_known_default();
PoolKey {
hostname: url.host_str().unwrap_or(DEFAULT_HOST).into(),
port: port.expect("Failed to get port for pool key"),
scheme: url.scheme().to_string(),
hostname: url.host_str().unwrap_or("").to_string(),
port,
}
}
}
#[test]
fn poolkey_new() {
// Test that PoolKey::new() does not panic on unrecognized schemes.
PoolKey::new(&Url::parse("zzz:///example.com").unwrap());
}
/// Read wrapper that returns the stream to the pool once the
/// read is exhausted (reached a 0).
///