Monorepo consolidation: workspace, shared types, transport plans, docker/swam assets
This commit is contained in:
99
gateway/src/upstream.rs
Normal file
99
gateway/src/upstream.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn http_client() -> &'static reqwest::Client {
|
||||
static CLIENT: OnceLock<reqwest::Client> = OnceLock::new();
|
||||
CLIENT.get_or_init(|| {
|
||||
let mut builder = reqwest::Client::builder().timeout(Duration::from_secs(10));
|
||||
|
||||
if let Some(ca_pem) = env_or_file(
|
||||
"GATEWAY_INTERNAL_CA_CERT_PEM",
|
||||
"GATEWAY_INTERNAL_CA_CERT_PEM_FILE",
|
||||
) {
|
||||
if let Ok(cert) = reqwest::Certificate::from_pem(ca_pem.as_bytes()) {
|
||||
builder = builder.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(identity_pem) = env_or_file(
|
||||
"GATEWAY_INTERNAL_IDENTITY_PEM",
|
||||
"GATEWAY_INTERNAL_IDENTITY_PEM_FILE",
|
||||
) {
|
||||
if let Ok(identity) = reqwest::Identity::from_pem(identity_pem.as_bytes()) {
|
||||
builder = builder.identity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
builder.build().expect("failed to build reqwest client")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn grpc_endpoint(url: &str) -> Result<tonic::transport::Endpoint, tonic::transport::Error> {
|
||||
let mut endpoint =
|
||||
tonic::transport::Endpoint::from_shared(url.to_string())?.timeout(Duration::from_secs(10));
|
||||
|
||||
let wants_tls = url.starts_with("https://")
|
||||
|| std::env::var("GATEWAY_INTERNAL_GRPC_TLS")
|
||||
.ok()
|
||||
.map(|v| matches!(v.trim().to_ascii_lowercase().as_str(), "1" | "true" | "yes"))
|
||||
.unwrap_or(false);
|
||||
|
||||
if wants_tls {
|
||||
if let Some(tls) = grpc_tls_config() {
|
||||
endpoint = endpoint.tls_config(tls)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(endpoint)
|
||||
}
|
||||
|
||||
fn grpc_tls_config() -> Option<tonic::transport::ClientTlsConfig> {
|
||||
let mut tls = tonic::transport::ClientTlsConfig::new();
|
||||
let mut configured = false;
|
||||
|
||||
if let Some(ca_pem) = env_or_file(
|
||||
"GATEWAY_INTERNAL_GRPC_CA_CERT_PEM",
|
||||
"GATEWAY_INTERNAL_GRPC_CA_CERT_PEM_FILE",
|
||||
) {
|
||||
tls = tls.ca_certificate(tonic::transport::Certificate::from_pem(ca_pem));
|
||||
configured = true;
|
||||
}
|
||||
|
||||
let cert_pem = env_or_file(
|
||||
"GATEWAY_INTERNAL_GRPC_CLIENT_CERT_PEM",
|
||||
"GATEWAY_INTERNAL_GRPC_CLIENT_CERT_PEM_FILE",
|
||||
);
|
||||
let key_pem = env_or_file(
|
||||
"GATEWAY_INTERNAL_GRPC_CLIENT_KEY_PEM",
|
||||
"GATEWAY_INTERNAL_GRPC_CLIENT_KEY_PEM_FILE",
|
||||
);
|
||||
if let (Some(cert_pem), Some(key_pem)) = (cert_pem, key_pem) {
|
||||
tls = tls.identity(tonic::transport::Identity::from_pem(cert_pem, key_pem));
|
||||
configured = true;
|
||||
}
|
||||
|
||||
if configured {
|
||||
Some(tls)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn env_or_file(env_key: &str, file_env_key: &str) -> Option<String> {
|
||||
if let Ok(path) = std::env::var(file_env_key) {
|
||||
if let Ok(raw) = std::fs::read_to_string(path) {
|
||||
let trimmed = raw.trim().to_string();
|
||||
if !trimmed.is_empty() {
|
||||
return Some(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::env::var(env_key).ok().and_then(|v| {
|
||||
let trimmed = v.trim().to_string();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(trimmed)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user