use anyhow::{Context, Result};
use async_trait::async_trait;
use hyper::client::HttpConnector;
use hyper::{Body, Client as HyperClient, Method, Request, Uri};
use hyper_tls::HttpsConnector;
use std::collections::HashMap;
use std::str::FromStr;
use url::Url;
use crate::report::Report;
use crate::tasks::{Params as TaskParams, Task};
use crate::utils::timestamp::current_timestamp;
use crate::worker::perform::Perform;
use super::{Params, Report as HttpReport};
#[allow(dead_code)]
pub struct Provider {
task_title: String,
http_client: HyperClient<HttpsConnector<HttpConnector>>,
http_method: Method,
params: Params,
url: String,
}
impl Provider {
pub fn new(task: Task) -> Result<Self> {
let params = match task.params {
TaskParams::Http(p) => p,
};
let url = Url::from_str(params.url.as_str())
.context(format!("Invalid URL provided for task {}", task.id))?;
let http_client = HyperClient::builder().build(HttpsConnector::new());
let http_method = Method::from_str(params.method.as_str())
.context(format!("Invalid HTTP Method provided for task {}", task.id))?;
Ok(Self {
task_title: task.id,
http_client,
http_method,
params,
url: url.to_string(),
})
}
}
#[async_trait]
impl Perform for Provider {
async fn perform(&self) -> Result<Report> {
let req_start = current_timestamp();
let request = Request::builder()
.uri(Uri::from_str(self.url.as_str()).unwrap())
.method(self.http_method.clone())
.body(Body::empty())
.context(format!(
"Failed to build Request struct on {}",
self.task_title
))?;
let response = self.http_client.request(request).await.unwrap();
let mut headers: HashMap<String, String> = HashMap::new();
for (k, v) in response.headers() {
headers.insert(k.to_string(), v.to_str().unwrap().to_string());
}
let http_report = HttpReport {
id: self.task_title.clone(),
status_code: response.status().as_u16(),
headers,
req_start,
req_end: current_timestamp(),
};
Ok(Report::Http(http_report))
}
}