use std::time::Duration;
use hyper_util::client::legacy::connect::HttpConnector;
pub const TCP_KEEPALIVE_TIME: Duration = Duration::from_secs(60);
pub const TCP_KEEPALIVE_INTERVAL: Duration = Duration::from_secs(15);
pub const TCP_KEEPALIVE_RETRIES: u32 = 4;
pub fn http_connector(connection_timeout: Duration) -> HttpConnector {
let mut connector = HttpConnector::new();
connector.set_connect_timeout(Some(connection_timeout));
connector.set_nodelay(true);
connector.set_keepalive(Some(TCP_KEEPALIVE_TIME));
connector.set_keepalive_interval(Some(TCP_KEEPALIVE_INTERVAL));
connector.set_keepalive_retries(Some(TCP_KEEPALIVE_RETRIES));
connector
}
#[cfg(test)]
mod tests {
use super::*;
use tower_service::Service;
#[tokio::test]
async fn connections_carry_keepalive_and_nodelay() {
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.expect("bind");
let addr = listener.local_addr().expect("addr");
let accept = tokio::spawn(async move { listener.accept().await });
let mut connector = http_connector(Duration::from_secs(5));
let uri: hyper::Uri = format!("http://{addr}").parse().expect("uri");
let io = connector.call(uri).await.expect("connect");
let tcp = io.inner();
let sock = socket2::SockRef::from(tcp);
assert!(sock.keepalive().expect("SO_KEEPALIVE"), "keepalive is on");
assert!(tcp.nodelay().expect("TCP_NODELAY"), "nodelay is on");
#[cfg(target_os = "linux")]
{
assert_eq!(sock.tcp_keepalive_time().expect("idle"), TCP_KEEPALIVE_TIME);
assert_eq!(
sock.tcp_keepalive_interval().expect("interval"),
TCP_KEEPALIVE_INTERVAL
);
assert_eq!(
sock.tcp_keepalive_retries().expect("retries"),
TCP_KEEPALIVE_RETRIES
);
}
drop(accept.await);
}
#[test]
fn keepalive_constants() {
assert_eq!(TCP_KEEPALIVE_TIME, Duration::from_secs(60));
assert_eq!(TCP_KEEPALIVE_INTERVAL, Duration::from_secs(15));
assert_eq!(TCP_KEEPALIVE_RETRIES, 4);
}
}