use reqwest::{Client, ClientBuilder, Proxy, header::{HeaderMap, HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue}};
use rand::seq::SliceRandom;
use std::str::FromStr;
#[derive(Debug)]
pub enum Error {
Reqwest(reqwest::Error),
InvalidHeaderName(InvalidHeaderName),
InvalidHeaderValue(InvalidHeaderValue),
SerdeJson(serde_json::Error), }
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Error::Reqwest(err)
}
}
impl From<InvalidHeaderName> for Error {
fn from(err: InvalidHeaderName) -> Self {
Error::InvalidHeaderName(err)
}
}
impl From<InvalidHeaderValue> for Error {
fn from(err: InvalidHeaderValue) -> Self {
Error::InvalidHeaderValue(err)
}
}
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Error::SerdeJson(err)
}
}
pub mod e9571_http_pro_lib {
use super::{Error, HeaderMap, HeaderName, HeaderValue};
use reqwest::{Client, ClientBuilder, Proxy, RequestBuilder};
use serde_json::{json, Value};
use std::collections::HashMap;
use std::time::Duration;
use std::str::FromStr;
use rand::prelude::IndexedRandom;
fn random_ua() -> &'static str {
let user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
];
user_agents.choose(&mut rand::rng()).unwrap_or(&user_agents[0])
}
pub async fn marmot_worker(
url: &str,
config: Option<HashMap<String, String>>,
json_value: Option<&Value>,
request_type: &str,
proxy: Option<&str>,
) -> Result<(String, serde_json::Value), Error> {
let mut client_builder = ClientBuilder::new()
.user_agent(random_ua())
.timeout(Duration::from_secs(30));
if let Some(proxy_url) = proxy {
if !proxy_url.is_empty() {
let proxy = Proxy::all(proxy_url)?;
client_builder = client_builder.proxy(proxy);
}
}
let client = client_builder.build()?;
let mut headers = HeaderMap::new();
if let Some(config_map) = config {
for (key, value) in config_map {
let header_name = HeaderName::from_str(&key)?;
let header_value = HeaderValue::from_str(&value)?;
headers.insert(header_name, header_value);
}
}
let mut request_builder = match request_type.to_lowercase().as_str() {
"get" => client.get(url),
"post" => {
headers.insert("Content-Type", HeaderValue::from_static("application/x-www-form-urlencoded"));
let default_json = json!({});
let form_data = json_value.unwrap_or(&default_json);
client.post(url).form(form_data)
},
"postjson" => {
headers.insert("Content-Type", HeaderValue::from_static("application/json"));
let default_json = json!({});
let json_data = json_value.unwrap_or(&default_json);
client.post(url).json(json_data)
},
"delete" => client.delete(url),
"put" => {
headers.insert("Content-Type", HeaderValue::from_static("application/json"));
let default_json = json!({});
let json_data = json_value.unwrap_or(&default_json);
client.put(url).json(json_data)
},
"putjson" => {
headers.insert("Content-Type", HeaderValue::from_static("application/json"));
let default_json = json!({});
let json_data = json_value.unwrap_or(&default_json);
client.put(url).json(json_data)
},
_ => client.get(url),
};
request_builder = request_builder.headers(headers.clone());
let response = request_builder.send().await?;
let response_headers = response.headers().clone();
let body = response.text().await?;
let headers_json = json!(response_headers
.iter()
.map(|(k, v)| (k.as_str().to_string(), v.to_str().unwrap_or("").to_string()))
.collect::<HashMap<String, String>>());
Ok((body, headers_json))
}
pub async fn create_url_data_get_header(
url: &str,
config: HashMap<String, String>,
) -> Result<(String, serde_json::Value), Error> {
marmot_worker(url, Some(config), None, "get", None).await
}
pub async fn create_url_data_get_header_proxy(
url: &str,
config: HashMap<String, String>,
proxy: &str,
) -> Result<(String, serde_json::Value), Error> {
marmot_worker(url, Some(config), None, "get", Some(proxy)).await
}
pub async fn marmot_worker_post_form(
url: &str,
config: Option<HashMap<String, String>>,
form_data: HashMap<String, String>,
) -> Result<(String, serde_json::Value), Error> {
let form_json = json!(form_data);
marmot_worker(url, config, Some(&form_json), "post", None).await
}
pub async fn marmot_worker_post_json<T: serde::Serialize>(
url: &str,
config: Option<HashMap<String, String>>,
json_data: &T,
) -> Result<(String, serde_json::Value), Error> {
let json_value = serde_json::to_value(json_data)?;
marmot_worker(url, config, Some(&json_value), "postjson", None).await
}
pub async fn post_json<T: serde::Serialize>(url: &str, data: &T) -> Result<String, Error> {
let client = Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let response = client
.post(url)
.header("Content-Type", "application/json")
.json(data)
.send()
.await?;
let body = response.text().await?;
Ok(body)
}
}