use std::collections::HashMap;
use std::error::Error;
use super::{ToUrl, Url};
use super::errors::NanoGetError;
use super::http::request_http_get;
#[cfg(feature = "https")]
use super::https::request_https_get;
use super::Response;
#[derive(Debug)]
pub struct Request {
pub url: Url,
request_type: RequestType,
headers: Option<HashMap<String, String>>,
pub body: Option<String>,
}
#[allow(dead_code)]
#[derive(Debug)]
enum RequestType {
HEAD,
GET,
PUT,
POST,
DELETE,
OPTIONS,
CUSTOM(String),
}
impl RequestType {
fn value(&self) -> &'static str {
match self {
RequestType::GET => "GET",
RequestType::HEAD => "HEAD",
RequestType::POST => "POST",
RequestType::PUT => "PUT",
RequestType::DELETE => "DELETE",
RequestType::OPTIONS => "OPTIONS",
RequestType::CUSTOM(_) => "CUSTOM",
}
}
}
pub type Header<'a> = (&'a str, &'a str);
impl Request {
pub fn new<A: ToUrl>(url: A, headers: Option<Vec<Header>>, body: Option<String>) -> Result<Self, Box<dyn Error>> {
let url = url.to_url()?;
let mut request = Request {
url,
request_type: RequestType::GET,
headers: None,
body,
};
request.headers = Some(Self::get_default_headers(&request.url));
let addnl_headers = process_headers(headers);
request.merge_addnl_headers(addnl_headers);
Ok(request)
}
fn merge_addnl_headers(&mut self, addnl_headers: Option<HashMap<String, String>>) {
if self.headers.is_some() {
let headers = self.headers.as_mut().unwrap();
if let Some(extra_headers) = addnl_headers {
for (k, v) in extra_headers {
headers.insert(k, v);
}
}
} else {
self.headers = addnl_headers;
}
}
pub fn default_get_request<A: ToUrl>(url: A) -> Result<Self, Box<dyn Error>> {
Self::new(url, None, None)
}
fn get_default_headers(url: &Url) -> HashMap<String, String> {
let mut headers = HashMap::with_capacity(4);
headers.insert("user-agent".to_string(), "mini-get/0.1.0".to_string());
headers.insert("accept".to_string(), "*/*".to_string());
headers.insert("host".to_string(), url.host.clone());
headers.insert("connection".to_string(), "close".to_string());
headers
}
pub fn execute(&self) -> Result<Response, NanoGetError> {
#[cfg(feature = "https")] {
if self.is_https() {
return request_https_get(&self);
}
}
request_http_get(&self)
}
pub fn get_request_headers(&self) -> impl Iterator<Item=(&str, &str)> {
self.headers.as_ref().unwrap().iter().map(|(k, v)| {
(k.as_str(), v.as_str())
})
}
pub fn is_https(&self) -> bool {
self.url.protocol.as_str() == "https"
}
pub fn get_request_type(&self) -> &str {
self.request_type.value()
}
pub fn add_header(&mut self, key: &str, value: &str) {
if self.headers.is_some() {
self.headers.as_mut().unwrap().insert((*key).to_string(), (*value).to_string());
} else {
let mut headers = HashMap::new();
headers.insert((*key).to_string(), (*value).to_string());
self.headers = Some(headers);
}
}
}
fn process_headers(headers: Option<Vec<Header>>) -> Option<HashMap<String, String>> {
headers.map(|vec| {
vec.iter().cloned().map(|(k, v)| (k.to_string(), v.to_string())).collect()
})
}