// use crate::MyError;
use crate::{IResult, JsonV};
use reqwest::header::{HeaderMap, HeaderValue};
// use reqwest::Method;
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::str::FromStr;
// use std::path::Path;
// use std::str::FromStr;
use std::time::Duration;
fn get_haeders() -> Result<HeaderMap, String> {
let mut haeders = HeaderMap::new();
haeders.insert(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0"
.parse::<HeaderValue>()
.map_err(|e| e.to_string())?,
);
haeders.insert(
"Accept",
"text/html,application/xhtml+xml,application/xml;application/json;q=0.9,image/webp,*/*;q=0.8"
.parse::<HeaderValue>()
.map_err(|e| e.to_string())?,
);
haeders.insert(
"Accept-Language",
"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2".parse::<HeaderValue>().map_err(|e| e.to_string())?,
);
// haeders.insert("Connection", "Close".parse()?);
haeders.insert("Cache-Control", "no-cache".parse::<HeaderValue>().map_err(|e| e.to_string())?);
Ok(haeders)
}
/// form表单提交数据
#[cfg(feature = "use_blocking")]
pub fn form(url: impl AsRef<std::path::Path>, form_params: HashMap<String, String>) -> IResult<String> {
let mut form = reqwest::blocking::multipart::Form::new();
for (k, v) in form_params {
form = form.text(k, v);
}
let client = reqwest::blocking::Client::new();
let resp = client.post(url.as_ref().to_str().unwrap_or_default()).multipart(form).send()?.text()?;
Ok(resp)
}
/*#[test]
fn test_form() {
let r = form("http://www.baidu.com", HashMap::new());
println!("{:?}", r)
}*/
// 上传文件
/*pub fn upload_file(
url: impl AsRef<Path>,
form_params: HashMap<String, String>,
file_path: impl AsRef<Path>,
) -> IResult<String> {
let mut form = reqwest::blocking::multipart::Form::new().file("file", file_path)?;
for (k, v) in form_params {
form = form.text(k, v);
}
let client = reqwest::blocking::Client::new();
let resp = client
.post(url.as_ref().to_str().unwrap_or_default())
.multipart(form)
.send()?
.text()?;
Ok(resp)
}*/
/*#[test]
fn test_uplod_file() {
let r = upload_file("http://www.baidu.com", HashMap::new(), file!());
println!("{:?}", r)
}*/
#[allow(dead_code)]
fn get_haeders2(body: &str) -> IResult<HeaderMap> {
let mut haeders = get_haeders()?;
haeders.insert("Content-Length", body.len().to_string().parse()?);
Ok(haeders)
}
pub enum Body {
String(String),
File(File),
Null,
}
impl From<JsonV> for Body {
fn from(v: JsonV) -> Self {
if !v.is_null() {
Self::String(v.to_string())
} else {
Self::Null
}
}
}
impl From<File> for Body {
fn from(v: File) -> Self {
Self::File(v)
}
}
impl From<&str> for Body {
fn from(v: &str) -> Self {
Self::String(v.to_string())
}
}
impl From<String> for Body {
fn from(v: String) -> Self {
Self::String(v)
}
}
pub trait Headers {
fn headers(self) -> HashMap<String, String>;
}
impl Headers for HashMap<String, String> {
fn headers(self) -> HashMap<String, String> {
self
}
}
impl Headers for JsonV {
fn headers(self) -> HashMap<String, String> {
self.as_object()
.map(|v| {
let mut map = HashMap::new();
for (k, v) in v {
map.insert(k.to_string(), v.as_str().unwrap_or_default().to_string());
}
map
})
.unwrap_or_default()
}
}
// 使用cookie进行请求post
pub async fn req_with_header(url: String, input_headers: impl Headers, method: &str, body: impl Into<Body>) -> IResult<JsonV> {
let mut haeders = HeaderMap::new();
for (k, v) in input_headers.headers().iter() {
let k = k.to_string();
haeders.insert(reqwest::header::HeaderName::from_str(k.as_str())?, v.as_str().parse::<HeaderValue>().map_err(|e| e.to_string())?);
}
let client = reqwest::ClientBuilder::new().build()?;
let method = match method.to_lowercase().trim() {
"get" => reqwest::Method::GET,
"post" => reqwest::Method::POST,
_ => Err(format!("请求方法不受支持: {}", method))?,
};
let mut build = client.request(method, url).headers(haeders).timeout(Duration::from_secs(15));
let body = body.into();
match body {
Body::File(mut f) => {
let mut r = vec![];
f.read_to_end(&mut r)?;
build = build.body(r);
}
Body::String(s) => {
build = build.body(s);
}
Body::Null => (),
}
debug!("req_with_header: {:?}", build);
let text = build.send().await?.text().await?;
let res = serde_json::from_str::<JsonV>(text.as_str()).unwrap_or_else(|_e| JsonV::String(text));
return Ok(res);
}
#[cfg(test)]
mod test {
use super::*;
#[tokio::test]
async fn test_req_with_header() -> IResult {
let r = req_with_header("http://api.qichacha.com/ECIV4/Search?key=sdf&keyword=1".to_string(), JsonV::Null, "get", JsonV::Null).await?;
println!("test_req_with_header: {}", r.to_string());
Ok(())
}
}
pub async fn req_with_header_t<T: DeserializeOwned>(url: String, input_headers: impl Headers, method: &str, body: impl Into<Body>) -> IResult<T> {
let r = req_with_header(url, input_headers, method, body).await?;
let r = serde_json::from_value(r)?;
Ok(r)
}
pub async fn post_json<T: DeserializeOwned>(url: String, json_v: JsonV) -> IResult<T> {
let text = reqwest::Client::new()
.post(url.as_str())
.json(&json_v)
.headers(get_haeders()?)
.header("Content-Type", "application/json;charset=utf-8")
.timeout(Duration::from_secs(15))
.send()
.await?
.text()
.await?;
let r = serde_json::from_str::<T>(text.as_str());
return match r {
Ok(v) => Ok(v),
Err(e) => {
warn!("{}", text);
Err(e)?
}
};
}
pub async fn get_json<T: DeserializeOwned>(url: String) -> IResult<T> {
let head = get_haeders()?;
let text = reqwest::Client::new()
.get(url.as_str())
.headers(head)
.header("Content-Type", "application/json;charset=utf-8")
.timeout(Duration::from_secs(15))
.send()
.await?
.text()
.await?;
let r = serde_json::from_str::<T>(text.as_str());
return match r {
Ok(v) => Ok(v),
Err(e) => {
warn!("{}", text);
Err(e)?
}
};
}
/*#[test]
pub fn test_post_vec() {
let body = r##"{"error_info":null,"data":{"data_id":null,"account_id":"96693efe7f3840e7b5c34cc90c33a9df","now_id":660,"type_title":"登录","created_datetime":"2020-12-23 12:08:59","error_info":null,"created_data":1608696539,"start_date":null,"end_date":null,"json_data":"正常"},"account":{"account_id":"96693efe7f3840e7b5c34cc90c33a9df","user_id":null,"company_name":null,"account_name":"91430105MA4LJQY047","account_password":"cszj131419","status":"帐户正常","last_get_data":null,"run_time":1608696509,"updated_time":1608696539,"created_time":1608696539}}"##;
let r = post_json(
"https://dsp.zgaic.com/fas/Tax/TaxpayerInformation".to_owned(),
serde_json::from_str(body).unwrap(),
)
.await;
println!("test_post_vec: {:?}", r);
}*/
pub async fn get(url: String) -> IResult<String> {
let r = reqwest::Client::new().get(&url).headers(get_haeders()?).send().await?.text().await?;
Ok(r)
}
pub async fn get_vec(url: String) -> IResult<Vec<u8>> {
let r = reqwest::Client::new().get(&url).headers(get_haeders()?).send().await?.bytes().await?.to_vec();
Ok(r)
}
/*#[test]
fn test_get_vec() -> IResult<()> {
use std::fs::File;
use std::io::Write;
let bytes =
get_vec("https://necaptcha.nosdn.127.net/d0cee769c8fa476b957af7f222972f6c.jpg".to_owned())
.await;
let mut file = File::create("测试.jpg").map_err(|e| format!("新建图片错误: {:?}", e))?;
file.write_all(bytes.as_slice())
.map_err(|e| format!("下载图片[write_all]错误: {:?}", e))?;
Ok(())
}*/