fix: run cert check concurrently with request so a hanging TCP connect can't block the timeout
This commit is contained in:
parent
b41faff2ad
commit
dbbc9c00cc
|
|
@ -70,16 +70,6 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Op
|
||||||
let method = monitor.method.as_deref().unwrap_or("GET").to_uppercase();
|
let method = monitor.method.as_deref().unwrap_or("GET").to_uppercase();
|
||||||
let timeout = std::time::Duration::from_millis(monitor.timeout_ms.unwrap_or(30000));
|
let timeout = std::time::Duration::from_millis(monitor.timeout_ms.unwrap_or(30000));
|
||||||
|
|
||||||
// Check cert expiry for HTTPS URLs — bounded by the same timeout
|
|
||||||
let cert_expiry_days = if monitor.url.starts_with("https://") {
|
|
||||||
match tokio::time::timeout(timeout, check_cert_expiry(&monitor.url)).await {
|
|
||||||
Ok(Ok(days)) => days,
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let req_method = reqwest::Method::from_bytes(method.as_bytes())
|
let req_method = reqwest::Method::from_bytes(method.as_bytes())
|
||||||
.unwrap_or(reqwest::Method::GET);
|
.unwrap_or(reqwest::Method::GET);
|
||||||
|
|
||||||
|
|
@ -100,9 +90,21 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Op
|
||||||
req = req.body(body.clone());
|
req = req.body(body.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the entire request + body read in a single timeout so slow response
|
let is_https = monitor.url.starts_with("https://");
|
||||||
// bodies don't slip through after headers arrive within the window.
|
let url_clone = monitor.url.clone();
|
||||||
|
|
||||||
|
// Run the HTTP request and cert check concurrently, both under the same timeout.
|
||||||
|
// This prevents a hanging TCP connect in the cert check from blocking the whole check.
|
||||||
let timed = tokio::time::timeout(timeout, async {
|
let timed = tokio::time::timeout(timeout, async {
|
||||||
|
let cert_future = async {
|
||||||
|
if is_https {
|
||||||
|
check_cert_expiry(&url_clone).await.ok().flatten()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let req_future = async {
|
||||||
let resp = req.send().await?;
|
let resp = req.send().await?;
|
||||||
let status = resp.status();
|
let status = resp.status();
|
||||||
let headers: HashMap<String, String> = resp.headers().iter()
|
let headers: HashMap<String, String> = resp.headers().iter()
|
||||||
|
|
@ -121,6 +123,10 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Op
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok::<_, reqwest::Error>((status, headers, body))
|
Ok::<_, reqwest::Error>((status, headers, body))
|
||||||
|
};
|
||||||
|
|
||||||
|
let (cert_result, req_result) = tokio::join!(cert_future, req_future);
|
||||||
|
req_result.map(|(status, headers, body)| (status, headers, body, cert_result))
|
||||||
}).await;
|
}).await;
|
||||||
|
|
||||||
let latency_ms = start.elapsed().as_millis() as u64;
|
let latency_ms = start.elapsed().as_millis() as u64;
|
||||||
|
|
@ -141,10 +147,10 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor, scheduled_at: Op
|
||||||
latency_ms: Some(latency_ms),
|
latency_ms: Some(latency_ms),
|
||||||
up: false,
|
up: false,
|
||||||
error: Some(e),
|
error: Some(e),
|
||||||
cert_expiry_days,
|
cert_expiry_days: None,
|
||||||
meta: None,
|
meta: None,
|
||||||
},
|
},
|
||||||
Ok((status_raw, headers, body)) => {
|
Ok((status_raw, headers, body, cert_expiry_days)) => {
|
||||||
let status = status_raw.as_u16();
|
let status = status_raw.as_u16();
|
||||||
|
|
||||||
// Evaluate query if present
|
// Evaluate query if present
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue