use crate::error::OAuthError;
use std::time::Duration;
pub(crate) const OAUTH_HTTP_TIMEOUT: Duration = Duration::from_secs(10);
pub(crate) const OAUTH_HTTP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5);
pub(crate) fn build_http_client(
timeout: Duration,
connect_timeout: Duration,
) -> Result<reqwest::Client, OAuthError> {
reqwest::Client::builder()
.timeout(timeout)
.connect_timeout(connect_timeout)
.build()
.map_err(|e| OAuthError::Internal {
message: "failed to build OAuth HTTP client".into(),
source: Box::new(e),
})
}
pub(crate) fn default_http_client() -> Result<reqwest::Client, OAuthError> {
build_http_client(OAUTH_HTTP_TIMEOUT, OAUTH_HTTP_CONNECT_TIMEOUT)
}
#[cfg(test)]
mod tests {
use super::*;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
#[tokio::test]
async fn enforces_request_timeout_instead_of_hanging() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/slow"))
.respond_with(ResponseTemplate::new(200).set_delay(Duration::from_secs(2)))
.mount(&server)
.await;
let client = build_http_client(Duration::from_millis(50), Duration::from_millis(50))
.expect("client builds");
let err = client
.get(format!("{}/slow", server.uri()))
.send()
.await
.expect_err("a slow IdP must time out, not hang");
assert!(err.is_timeout(), "expected a timeout error, got {err:?}");
}
}