use crate::options::Cli;
use crate::report::Response;
use crate::storage::store_response_on_disk;
use base64::Engine;
use std::error::Error;
use std::path::PathBuf;
use std::time::Duration;
pub fn build_client(options: &Cli) -> Result<reqwest::Client, Box<dyn Error>> {
let mut client_builder = reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.user_agent(options.user_agent.as_str())
.timeout(Duration::from_secs(options.request_timeout as u64));
if options.follow_redirects {
client_builder = client_builder.redirect(reqwest::redirect::Policy::limited(10));
}
if let Some(auth) = &options.basic_auth {
if !auth.is_empty() {
let mut headers = reqwest::header::HeaderMap::new();
let encoded_credentials =
base64::engine::general_purpose::STANDARD.encode(auth.as_bytes());
let auth_value = format!("Basic {}", encoded_credentials).parse()?;
headers.insert(reqwest::header::AUTHORIZATION, auth_value);
client_builder = client_builder.default_headers(headers);
}
}
Ok(client_builder.build()?)
}
pub async fn get_url_content(
url: &str,
client: &reqwest::Client,
) -> Result<String, reqwest::Error> {
client
.get(url)
.send()
.await?
.error_for_status()?
.text()
.await
}
pub async fn get_url_response(
url: &str,
client: &reqwest::Client,
output_dir: &Option<PathBuf>,
) -> Result<Response, reqwest::Error> {
let start_time = tokio::time::Instant::now();
let response = client.get(url).send().await;
let (status, url, content_length, body) = match response {
Ok(resp) => {
let url = Some(resp.url().clone());
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
(status, url, body.len(), Some(body))
}
Err(e) if e.is_timeout() => (reqwest::StatusCode::REQUEST_TIMEOUT, None, 0, None),
Err(e) if e.is_connect() => (reqwest::StatusCode::BAD_GATEWAY, None, 0, None),
Err(e) if e.is_request() => (reqwest::StatusCode::BAD_REQUEST, None, 0, None),
Err(e) => return Err(e),
};
if let (Some(output_dir), Some(url_ref)) = (output_dir, url.as_ref()) {
store_response_on_disk(output_dir, url_ref, body.unwrap_or_default().as_str()).await;
}
Ok(Response {
response_time: start_time.elapsed(),
response_size: content_length,
url: url.unwrap().to_string(),
status_code: status,
})
}