use std::time::Duration;
use tonic::transport::Channel;
pub fn normalize_grpc_endpoint(endpoint: &str) -> String {
match endpoint.split_once("://") {
Some(("grpc", rest)) => format!("http://{rest}"),
Some(("grpcs", rest)) => format!("https://{rest}"),
_ => endpoint.to_string(),
}
}
pub async fn connect_channel(
endpoint: &str,
) -> Result<Channel, Box<dyn std::error::Error + Send + Sync>> {
let http_endpoint = normalize_grpc_endpoint(endpoint);
let channel = Channel::from_shared(http_endpoint)?
.http2_keep_alive_interval(Duration::from_secs(30))
.keep_alive_timeout(Duration::from_secs(10))
.keep_alive_while_idle(true)
.tcp_keepalive(Some(Duration::from_secs(60)))
.tcp_nodelay(true)
.http2_adaptive_window(true)
.initial_stream_window_size(Some(16 * 1024 * 1024))
.initial_connection_window_size(Some(32 * 1024 * 1024))
.connect()
.await?;
Ok(channel)
}
#[cfg(test)]
mod tests {
use super::normalize_grpc_endpoint;
#[test]
fn normalize_grpc_to_http() {
assert_eq!(
normalize_grpc_endpoint("grpc://worker:8080"),
"http://worker:8080"
);
}
#[test]
fn normalize_grpcs_to_https() {
assert_eq!(
normalize_grpc_endpoint("grpcs://worker:8443"),
"https://worker:8443"
);
}
#[test]
fn normalize_passes_http_through() {
assert_eq!(
normalize_grpc_endpoint("http://worker:8080"),
"http://worker:8080"
);
}
#[test]
fn normalize_passes_https_through() {
assert_eq!(
normalize_grpc_endpoint("https://worker:8443"),
"https://worker:8443"
);
}
#[test]
fn normalize_passes_unknown_scheme_through() {
assert_eq!(
normalize_grpc_endpoint("tcp://worker:9000"),
"tcp://worker:9000"
);
}
#[test]
fn normalize_passes_schemeless_through() {
assert_eq!(normalize_grpc_endpoint("worker:8080"), "worker:8080");
}
#[test]
fn normalize_handles_path_after_authority() {
assert_eq!(
normalize_grpc_endpoint("grpc://worker:8080/some/path"),
"http://worker:8080/some/path"
);
}
#[test]
fn normalize_is_case_sensitive_on_scheme() {
assert_eq!(
normalize_grpc_endpoint("GRPC://worker:8080"),
"GRPC://worker:8080"
);
}
}