use a stale check in the pool
Check that a socket is not EOF to reduce the likelihood of using a bad pooled connection.
This commit is contained in:
@@ -10,8 +10,9 @@ license = "MIT/Apache-2.0"
|
||||
categories = ["web-programming::http-client"]
|
||||
|
||||
[dependencies]
|
||||
hyper = "0.10.2"
|
||||
hyper-native-tls = "0.2.3"
|
||||
hyper = "0.10.12"
|
||||
hyper-native-tls = "0.2.4"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::fmt;
|
||||
use std::net::TcpStream;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -9,7 +10,7 @@ use hyper::method::Method;
|
||||
use hyper::status::StatusCode;
|
||||
use hyper::Url;
|
||||
|
||||
use hyper_native_tls::{NativeTlsClient, native_tls};
|
||||
use hyper_native_tls::{NativeTlsClient, TlsStream, native_tls};
|
||||
|
||||
use body;
|
||||
use redirect::{self, RedirectPolicy, check_redirect, remove_sensitive_headers};
|
||||
@@ -153,14 +154,8 @@ impl ClientBuilder {
|
||||
tls_client.danger_disable_hostname_verification(true);
|
||||
}
|
||||
|
||||
let mut hyper_client = ::hyper::Client::with_connector(
|
||||
::hyper::client::Pool::with_connector(
|
||||
Default::default(),
|
||||
::hyper::net::HttpsConnector::new(tls_client),
|
||||
)
|
||||
);
|
||||
let mut hyper_client = create_hyper_client(tls_client);
|
||||
|
||||
hyper_client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone);
|
||||
hyper_client.set_read_timeout(config.timeout);
|
||||
hyper_client.set_write_timeout(config.timeout);
|
||||
|
||||
@@ -256,6 +251,88 @@ impl ClientBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_hyper_client(tls_client: NativeTlsClient) -> ::hyper::Client {
|
||||
let mut pool = ::hyper::client::Pool::with_connector(
|
||||
Default::default(),
|
||||
::hyper::net::HttpsConnector::new(tls_client),
|
||||
);
|
||||
// For now, while experiementing, they're constants.
|
||||
// TODO: maybe make these configurable someday?
|
||||
pool.set_idle_timeout(Some(Duration::from_secs(60 * 2)));
|
||||
pool.set_stale_check(|mut check| {
|
||||
if stream_dead(check.stream()) {
|
||||
check.stale()
|
||||
} else {
|
||||
check.fresh()
|
||||
}
|
||||
});
|
||||
|
||||
let mut hyper_client = ::hyper::Client::with_connector(pool);
|
||||
|
||||
hyper_client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone);
|
||||
hyper_client
|
||||
}
|
||||
|
||||
fn stream_dead(stream: &::hyper::net::HttpsStream<TlsStream<::hyper::net::HttpStream>>) -> bool {
|
||||
match *stream {
|
||||
::hyper::net::HttpsStream::Http(ref http) => socket_is_dead(&http.0),
|
||||
::hyper::net::HttpsStream::Https(ref https) => socket_is_dead(&https.lock().get_ref().0),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn socket_is_dead(socket: &TcpStream) -> bool {
|
||||
use std::mem;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::ptr;
|
||||
use libc::{FD_SET, select, timeval};
|
||||
|
||||
let ret = unsafe {
|
||||
let fd = socket.as_raw_fd();
|
||||
let nfds = fd + 1;
|
||||
|
||||
let mut timeout = timeval {
|
||||
tv_sec: 0,
|
||||
tv_usec: 0,
|
||||
};
|
||||
|
||||
let mut readfs = mem::zeroed();
|
||||
let mut errfs = mem::zeroed();
|
||||
FD_SET(fd, &mut readfs);
|
||||
FD_SET(fd, &mut errfs);
|
||||
select(nfds, &mut readfs, ptr::null_mut(), &mut errfs, &mut timeout)
|
||||
};
|
||||
|
||||
// socket was readable (eof), or an error, then it's dead
|
||||
ret != 0
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn socket_is_dead(socket: &TcpStream) -> bool {
|
||||
use std::mem;
|
||||
use std::os::windows::io::AsRawSocket;
|
||||
use std::ptr;
|
||||
use libc::{FD_SET, select, timeval};
|
||||
|
||||
let ret = unsafe {
|
||||
let fd = socket.as_raw_socket();
|
||||
let nfds = 0; // msdn says nfds is ignored
|
||||
let timeout = timeval {
|
||||
tv_sec: 0,
|
||||
tv_usec: 0,
|
||||
};
|
||||
|
||||
let mut readfs = mem::zeroed();
|
||||
let mut errfs = mem::zeroed();
|
||||
FD_SET(fd, &mut readfs);
|
||||
FD_SET(fd, &mut errfs);
|
||||
select(nfds, &mut readfs, ptr::null_mut(), &mut errfs, &mut timeout)
|
||||
};
|
||||
|
||||
// socket was readable (eof), or an error, then it's dead
|
||||
ret != 0
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// Constructs a new `Client`.
|
||||
///
|
||||
|
||||
@@ -123,6 +123,7 @@ extern crate hyper;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate libc;
|
||||
extern crate libflate;
|
||||
extern crate hyper_native_tls;
|
||||
extern crate serde;
|
||||
|
||||
Reference in New Issue
Block a user