mirror of
https://github.com/sadoyan/aralez.git
synced 2026-10-22 21:51:35 +08:00
198 lines
6.0 KiB
Rust
198 lines
6.0 KiB
Rust
use crate::utils::grpc::ping_grpc;
|
|
use bytes::Bytes;
|
|
use pingora_core::connectors::http::Connector;
|
|
use pingora_core::listeners::ALPN;
|
|
use pingora_core::prelude::HttpPeer;
|
|
use pingora_http::RequestHeader;
|
|
use std::sync::LazyLock;
|
|
use std::time::Duration;
|
|
|
|
pub static HC_CONNECTOR: LazyLock<Connector> = LazyLock::new(|| Connector::new(None));
|
|
|
|
pub struct HttpClientRequest<'a> {
|
|
pub method: &'a str,
|
|
pub tls: bool,
|
|
pub host: &'a str,
|
|
pub path: &'a str,
|
|
pub address: &'a str,
|
|
pub port: u16,
|
|
pub url: &'a str,
|
|
pub payload: Bytes,
|
|
}
|
|
|
|
pub async fn httpclient(req: HttpClientRequest<'_>) -> (bool, bool) {
|
|
let HttpClientRequest {
|
|
method,
|
|
tls,
|
|
host,
|
|
path,
|
|
address,
|
|
port,
|
|
url,
|
|
payload,
|
|
} = req;
|
|
let method = match method {
|
|
"HEAD" => "HEAD",
|
|
"GET" => "GET",
|
|
"POST" => "POST",
|
|
_ => "GET",
|
|
};
|
|
|
|
let mut peer = HttpPeer::new((address, port), tls, host.to_string());
|
|
|
|
if tls {
|
|
peer.options.verify_cert = false;
|
|
peer.options.verify_hostname = false;
|
|
}
|
|
|
|
let mut is_h2 = false;
|
|
peer.options.total_connection_timeout = Option::from(Duration::from_secs(5));
|
|
peer.options.alpn = ALPN::H2H1;
|
|
|
|
let (mut http_session, _) = match HC_CONNECTOR.get_http_session(&peer).await {
|
|
Ok(s) => s,
|
|
Err(e) => {
|
|
if let Some(msg) = e.context {
|
|
log::warn!("{}, type: {}", msg.as_str(), e.etype.as_str());
|
|
} else {
|
|
log::warn!("Fail to connect to addr: {}, tls {}, host {}", address, tls, host);
|
|
}
|
|
return (false, false);
|
|
}
|
|
};
|
|
|
|
match http_session.as_http2() {
|
|
Some(_) => {
|
|
peer.options.alpn = ALPN::H2;
|
|
is_h2 = true;
|
|
}
|
|
None => {
|
|
if ping_grpc(url).await {
|
|
return (true, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
let mut req = match RequestHeader::build(method, path.as_bytes(), None) {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
log::warn!("Failed to build request: {}", e);
|
|
return (false, false);
|
|
}
|
|
};
|
|
|
|
req.insert_header("Host", host).ok();
|
|
let body_bytes = if method == "POST" {
|
|
req.insert_header("Content-Type", "application/json").ok();
|
|
req.insert_header("Content-Length", payload.len().to_string()).ok();
|
|
payload
|
|
} else {
|
|
Bytes::new()
|
|
};
|
|
if let Err(e) = http_session.write_request_header(Box::new(req)).await {
|
|
log::warn!("Write header failed: {}", e);
|
|
return (false, false);
|
|
}
|
|
if let Err(e) = http_session.write_request_body(body_bytes, true).await {
|
|
log::warn!("Write body failed: {}", e);
|
|
return (false, false);
|
|
}
|
|
let status = match http_session.read_response_header().await {
|
|
Ok(_) => http_session.response_header().map(|r| r.status.as_u16()).unwrap_or(500),
|
|
Err(e) => {
|
|
if !is_h2 && ping_grpc(url).await {
|
|
return (true, true);
|
|
}
|
|
log::warn!("Health Check read failed ({}) : {} - {}", if is_h2 { "H2" } else { "H1" }, host, e);
|
|
return (false, false);
|
|
}
|
|
};
|
|
HC_CONNECTOR.release_http_session(http_session, &peer, None).await;
|
|
((200..500).contains(&status), is_h2)
|
|
}
|
|
/*
|
|
pub async fn httpclient(method: &str, tls: bool, host: &str, path: &str, address: &str, port: u16, url: String) -> (bool, bool) {
|
|
let method = match method {
|
|
"HEAD" => "HEAD",
|
|
"GET" => "GET",
|
|
"POST" => "POST",
|
|
_ => "GET",
|
|
};
|
|
let mut peer = HttpPeer::new((address, port), tls, host.to_string());
|
|
|
|
if tls {
|
|
peer.options.verify_cert = false;
|
|
peer.options.verify_hostname = false;
|
|
}
|
|
|
|
let mut is_h2 = false;
|
|
peer.options.total_connection_timeout = Option::from(Duration::from_secs(5));
|
|
peer.options.alpn = ALPN::H2H1;
|
|
let (mut http_session, _) = match HC_CONNECTOR.get_http_session(&peer).await {
|
|
Ok(s) => s,
|
|
Err(e) => {
|
|
if let Some(msg) = e.context {
|
|
log::warn!("{}, type: {}", msg.as_str(), e.etype.as_str());
|
|
} else {
|
|
log::warn!("Fail to connect to addr: {}, tls {}, host {}", address, tls, host);
|
|
}
|
|
return (false, false);
|
|
}
|
|
};
|
|
|
|
match http_session.as_http2() {
|
|
Some(_) => {
|
|
peer.options.alpn = ALPN::H2;
|
|
is_h2 = true;
|
|
}
|
|
None => {
|
|
if ping_grpc(url.as_str()).await {
|
|
return (true, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
let mut req = match RequestHeader::build(method, path.as_bytes(), None) {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
log::warn!("Failed to build request: {}", e);
|
|
return (false, false);
|
|
}
|
|
};
|
|
|
|
req.insert_header("Host", host).ok();
|
|
|
|
if let Err(e) = http_session.write_request_header(Box::new(req)).await {
|
|
log::warn!("Write header failed: {}", e);
|
|
return (false, false);
|
|
}
|
|
|
|
let status = if is_h2 {
|
|
if let Err(e) = http_session.write_request_body(Bytes::new(), true).await {
|
|
log::warn!("Write body failed: {}", e);
|
|
return (false, false);
|
|
}
|
|
match http_session.read_response_header().await {
|
|
Ok(_) => http_session.response_header().map(|r| r.status.as_u16()).unwrap_or(500),
|
|
Err(e) => {
|
|
if ping_grpc(url.as_str()).await {
|
|
return (true, true);
|
|
}
|
|
log::warn!("Health Check H2 read failed: {} - {}", host, e);
|
|
return (false, false);
|
|
}
|
|
}
|
|
} else {
|
|
match http_session.read_response_header().await {
|
|
Ok(_) => http_session.response_header().map(|r| r.status.as_u16()).unwrap_or(500),
|
|
Err(e) => {
|
|
log::warn!("Health Check H1 read failed: {} - {}", e, host);
|
|
return (false, false);
|
|
}
|
|
}
|
|
};
|
|
HC_CONNECTOR.release_http_session(http_session, &peer, None).await;
|
|
((200..500).contains(&status), is_h2)
|
|
}
|
|
*/
|