use crate::{IResult, JsonV};
use isahc::prelude::Configurable;
// use isahc::prelude::Configurable;
// use isahc::prelude::*;
use isahc::{Body, ReadResponseExt};
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use std::path::Path;
// use std::time::Duration;
#[allow(dead_code)]
fn get_haeders<'a>() -> HashMap<&'a str, &'a str> {
let mut haeders = HashMap::new();
haeders.insert("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0");
haeders.insert("Accept", "text/html,application/xhtml+xml,application/xml;application/json;q=0.9,image/webp,*/*;q=0.8");
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");
// haeders.insert("Connection", "Close".parse()?);
haeders.insert("Cache-Control", "no-cache");
haeders
}
fn get_json_haeders<'a>() -> HashMap<&'a str, &'a str> {
let mut haeders = HashMap::new();
haeders.insert("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0");
haeders.insert("Accept", "text/html,application/xhtml+xml,application/xml;application/json;q=0.9,image/webp,*/*;q=0.8");
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");
haeders.insert("Content-Type", "application/json;charset=utf-8");
// haeders.insert("Connection", "Close".parse()?);
haeders.insert("Cache-Control", "no-cache");
haeders
}
#[cfg(feature = "req_timeout_30")]
const TIME_OUT: u64 = 30;
#[cfg(feature = "req_timeout_30")]
const TIME_OUT_CONNECT: u64 = 5;
#[cfg(feature = "req_timeout_60")]
const TIME_OUT: u64 = 60;
#[cfg(feature = "req_timeout_60")]
const TIME_OUT_CONNECT: u64 = 10;
#[cfg(all(feature = "req_timeout_30", feature = "req_timeout_60"))]
compile_error!("feature 'req_timeout_30' and feature 'req_timeout_60' cannot be enabled at the same time");
pub fn post_json<T: DeserializeOwned>(url: String, json_v: JsonV) -> IResult<T> {
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_headers(get_json_haeders());
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
let r = req.build()?.post(url, json_v.to_string())?.json::<T>()?;
Ok(r)
}
/// 使用cookie进行请求post
pub fn post_with_header(url: String, mut headers: HashMap<String, String>, body: impl Into<Body> + std::fmt::Debug) -> IResult<JsonV> {
let mut headers_default = get_json_haeders();
for (k, v) in headers.iter_mut() {
for x in v.to_string().chars() {
if !x.is_ascii() {
let vv = percent_encoding::percent_encode_byte(x as u8);
*v = v.replace(x, vv);
}
}
headers_default.insert(k, v);
}
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_headers(headers_default);
// for (k, v) in headers.iter_mut() {
// for x in v.to_string().chars() {
// if !x.is_ascii(){
// let vv = percent_encoding::percent_encode_byte(x as u8);
// *v = v.replace(x, vv);
// }
// }
// let v = v.to_string();
// req = req.default_header(k, v);
// }
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
let res = req
// .connect_timeout(Duration::from_secs(TIME_OUT))
// .timeout(Duration::from_secs(TIME_OUT))
.build()?
.post(url, body)?
.text()?;
let json_val = serde_json::from_str::<JsonV>(&res);
let r = match json_val {
Ok(v) => v,
Err(e) => {
warn!("post_with_header error: {:?} \nres:{}", e, res);
JsonV::String(res)
}
};
Ok(r)
}
#[test]
fn test_post_with_header() {
let r = post_with_header(
"https://blog.csdn.net/".to_string(),
hashmap! {|v: &str|v.to_string();
"Cookie" => "xxx离宇x",
},
"fdsafdsafsda",
);
println!("test_post_with_header: {:?}", r);
}
/// 使用cookie进行请求post
pub fn get_with_header(url: String, mut headers: HashMap<String, String>) -> IResult<JsonV> {
let mut headers_default = get_json_haeders();
for (k, v) in headers.iter_mut() {
for x in v.to_string().chars() {
if !x.is_ascii() {
let vv = percent_encoding::percent_encode_byte(x as u8);
*v = v.replace(x, vv);
}
}
headers_default.insert(k, v);
}
let mut req = isahc::HttpClientBuilder::new().default_headers(headers_default);
for (k, v) in headers.iter_mut() {
for x in v.to_string().chars() {
if !x.is_ascii() {
let vv = percent_encoding::percent_encode_byte(x as u8);
*v = v.replace(x, vv);
}
}
let v = v.to_string();
// println!("header-value: {}", v);
req = req.default_header(k, v);
}
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
let res = req
// .connect_timeout(Duration::from_secs(TIME_OUT))
// .timeout(Duration::from_secs(TIME_OUT))
.build()?
.get(url)?
.text()?;
let json_val = serde_json::from_str::<JsonV>(&res);
let r = match json_val {
Ok(v) => v,
Err(_e) => JsonV::String(res),
};
Ok(r)
}
#[test]
fn test_get_with_header() {
let map = hashmap! {|v: &str|v.to_owned();"guoyu" => "guog*%*&*&jadgo-郭宇-345325a08678)(*^fd"};
let _ = get_with_header("https://vip2.kdzwy.com/guanjia/#/home".to_string(), map);
}
pub fn get_json<T: DeserializeOwned>(url: String) -> IResult<T> {
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_headers(get_json_haeders());
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
// .timeout(Duration::from_secs(TIME_OUT))
let r = req.build()?.get(url)?.json::<T>()?;
Ok(r)
}
#[test]
pub fn test_post() {
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::<serde_json::Value>("https://dsp.zgaic.com/fas/Tax/TaxpayerInformation".to_owned(), serde_json::from_str(body).unwrap());
println!("test_post_vec: {}", r.unwrap().to_string());
}
pub fn get_vec(url: String) -> IResult<Vec<u8>> {
let mut buf = vec![];
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_headers(get_haeders());
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
// .timeout(Duration::from_secs(TIME_OUT))
req.build()?.get(url)?.copy_to(&mut buf)?;
Ok(buf)
}
pub fn get_file(url: String, path: impl Into<String>) -> IResult<()> {
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_headers(get_haeders());
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
// .timeout(Duration::from_secs(TIME_OUT))
req.build()?.get(url)?.copy_to_file(path.into())?;
Ok(())
}
pub fn update_file<T: DeserializeOwned>(url: String, file_name: String, buff: &[u8]) -> IResult<T> {
let file_name = percent_encoding::utf8_percent_encode(&file_name, percent_encoding::NON_ALPHANUMERIC).to_string();
#[allow(unused_mut)]
let mut req = isahc::HttpClientBuilder::new().default_header("file_name", file_name);
#[cfg(any(feature = "req_timeout_30", feature = "req_timeout_60"))]
{
req = req.connect_timeout(std::time::Duration::from_secs(TIME_OUT_CONNECT)).timeout(std::time::Duration::from_secs(TIME_OUT));
}
let r = req.build()?.post(url, buff)?.json::<T>()?;
Ok(r)
}
pub fn update_filepath<T: DeserializeOwned>(url: String, file_name: String, file_path: &Path) -> IResult<T> {
let r = std::fs::read(file_path)?;
update_file(url, file_name, r.as_slice())
}
#[test]
fn test_update_file() -> IResult<()> {
let r = match std::fs::read("C:/Users/guoyu/OneDrive/大算盘/“金三”个人所得税系统扣缴申报业务和技术标准/个人所得税扣缴申报标准说明.doc") {
Ok(v) => v,
Err(e) => {
eprintln!("std::fs::read: {:?}", &e);
Err(e)?
}
};
// let r = std::fs::read(
// "C:/Users/guoyu/OneDrive/桌面/才税之家企业服务有限公司_小企业会计准则财务报表_20200701_20200930 (1).xls",
// )?;
// 才税之家企业服务有限公司_小企业会计准则财务报表_20200701_20200930 (1).xls
let r = update_file::<JsonV>("http://127.0.0.1:8081/etax/file/upload".to_owned(), "test/个人所得税扣缴申报标准说明.doc".to_owned(), r.as_slice());
println!("update_file: {:?}", r);
Ok(())
}
#[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())?;
let mut file = File::create("测试0106.jpg").map_err(|e| format!("新建图片错误: {:?}", e))?;
file.write_all(bytes.as_slice()).map_err(|e| format!("下载图片[write_all]错误: {:?}", e))?;
Ok(())
}