use rand::seq::SliceRandom;
use std::{collections::HashMap, sync::Arc, time::Duration};
use reqwest::{
Client, Response,
header::{HeaderMap, HeaderName, HeaderValue},
};
use crate::{
query::QueryError,
sherlock_target_manifest::{RequestMethod, TargetInfo},
};
const USER_AGENTS: [&str; 8] = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:115.0) Gecko/20100101 Firefox/115.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 12.0; rv:115.0) Gecko/20100101 Firefox/115.0",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0",
];
#[derive(Debug)]
pub struct RequestResult {
pub username: Arc<str>,
pub site: Arc<str>,
pub info: Arc<TargetInfo>,
pub url: String,
pub url_probe: String,
pub response: Result<Response, QueryError>,
pub query_time: Duration,
}
pub struct RequestParams {
pub url: String,
pub headers: Option<HashMap<String, String>>,
pub timeout: Duration,
pub method: RequestMethod,
pub request_payload: Option<String>,
pub user_agent: Option<String>,
}
pub async fn make_request(client: &Client, params: RequestParams) -> color_eyre::Result<Response> {
let RequestParams {
url,
headers,
timeout,
method,
request_payload,
user_agent,
} = params;
let headers_map = headers
.unwrap_or_default()
.into_iter()
.map(|(key, value)| {
let header_name = key.parse::<HeaderName>().unwrap();
let header_value = value.parse::<HeaderValue>().unwrap();
(header_name, header_value)
})
.collect::<HeaderMap>();
let req_method = match method {
RequestMethod::Get => reqwest::Method::GET,
RequestMethod::Post => reqwest::Method::POST,
RequestMethod::Put => reqwest::Method::PUT,
RequestMethod::Head => reqwest::Method::HEAD,
};
let random_agent = USER_AGENTS
.choose(&mut rand::thread_rng())
.unwrap()
.to_owned();
let req_user_agent = user_agent.unwrap_or(random_agent.into());
let resp = client
.request(req_method, &url)
.headers(headers_map)
.header("User-Agent", req_user_agent)
.timeout(timeout)
.json(&request_payload)
.send()
.await?;
Ok(resp)
}