use std::fs::File;
use std::time::Duration;
use curl::easy::{Easy, List};
use json::{JsonValue, object};
use std::io::{Read, Write};
use std::str;
use crate::{files, tools};
use crate::files::file;
pub struct Http {
url: String,
curl: Easy,
body: String,
headers: Vec<String>,
cookies: Vec<String>,
pub res_headers: JsonValue,
filepath: String,
pub res_cookies: JsonValue,
}
impl Http {
pub fn url(url: &str) -> Self {
Self {
url: url.to_string(),
curl: Easy::new(),
body: String::new(),
headers: Vec::new(),
cookies: Vec::new(),
res_headers: object! {},
filepath: String::new(),
res_cookies: object! {},
}
}
pub fn authorization_bearer(&mut self, token: &str) -> &mut Self {
self.set_headers("Authorization", format!("Bearer {}", token).as_str());
self
}
pub fn debug(&mut self, open: bool) -> &mut Self {
self.curl.verbose(open).unwrap();
self
}
pub fn progress(&mut self, open: bool) -> &mut Self {
self.curl.progress(open).unwrap();
let mut i = 0.0;
self.curl.progress_function(move |total_download_bytes, cur_download_bytes, _total_upload_bytes, _cur_upload_bytes| {
if total_download_bytes > 0.0 {
if i != cur_download_bytes / total_download_bytes * 100.0 {
i = cur_download_bytes / total_download_bytes * 100.0;
println!("已下载:{}%", i);
}
} else {
if i > 0.0 {} else {
i = 1.0;
println!("已下载:0%");
}
}
true
}).expect("进度执行失败");
self
}
pub fn set_headers(&mut self, key: &str, value: &str) -> &mut Self {
self.headers.push(format!("{}:{}", key, value));
self
}
pub fn set_cookies(&mut self, key: &str, value: &str) -> &mut Self {
self.cookies.push(format!("{}={}", key, value));
self
}
pub fn auth(&mut self, username: &str, password: &str) -> &mut Self {
self.curl.username(username).unwrap();
self.curl.password(password).unwrap();
self
}
pub fn post(&mut self, data: JsonValue) -> &mut Self {
self.body = data.dump();
self.curl.post(true).unwrap();
self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
self
}
pub fn post_form(&mut self, data: JsonValue) -> &mut Self {
self.set_headers("content-type", "application/x-www-form-urlencoded");
self.body = data.dump();
self.curl.post(true).unwrap();
self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
self
}
pub fn post_json(&mut self, data: JsonValue) -> &mut Self {
self.set_headers("content-type", "application/json");
self.body = data.dump();
self.curl.post(true).unwrap();
self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
self
}
pub fn patch(&mut self, body: JsonValue) -> &mut Self {
self.curl.custom_request("PATCH").unwrap();
self.set_headers("content-type", "application/json");
self.body = body.dump();
self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
self
}
pub fn get(&mut self, data: JsonValue) -> &mut Self {
self.curl.get(true).unwrap();
if !data.is_empty() {
let mut url = "".to_string();
for (k, v) in data.entries() {
if url == "" {
url = format!("{}={}", k, v);
} else {
url = format!("{}&{}={}", url, k, v);
}
}
self.url = format!("{}?{}", self.url, url);
}
self
}
pub fn download(&mut self, filepath: &str) -> &mut Self {
self.filepath = filepath.to_string();
self
}
pub fn response(&mut self) -> JsonValue {
let mut headers = List::new();
for header in self.headers.clone() {
headers.append(header.as_str()).unwrap();
}
if !self.headers.is_empty() {
self.curl.http_headers(headers).unwrap();
}
let mut cookies = "".to_string();
for cookie in self.cookies.clone() {
if cookies == "" {
cookies = format!("{}", cookie);
} else {
cookies = format!("{};{}", cookies, cookie);
}
}
if !self.cookies.is_empty() {
self.curl.cookie(&*cookies).unwrap();
}
self.curl.accept_encoding("zlib,gzip,identity").unwrap();
self.curl.timeout(Duration::from_micros(5)).unwrap();
self.curl.connect_timeout(Duration::from_micros(5)).unwrap();
self.curl.url(self.url.as_str()).unwrap();
let mut body = Vec::new();
{
let mut transfer = self.curl.transfer();
transfer.header_function(|data| {
let str = str::from_utf8(data).unwrap();
let data = tools::string::split(str.to_string(), ":");
let key = data[0].as_str().unwrap().to_lowercase();
match key.as_str() {
"set-cookie" => {
let kv = tools::string::split(data[1].to_string(), ";");
let cookie = kv[0].as_str().unwrap().trim();
let kv = tools::string::split(cookie.to_string(), "=");
for index in 0..kv.len() {
let k = kv[0].clone();
if index == 0 {
self.res_cookies[k.as_str().unwrap()] = "".into();
} else {
if kv[index] == "" {
self.res_cookies[k.as_str().unwrap()] = format!("{}=", self.res_cookies[k.as_str().unwrap()]).into();
} else {
self.res_cookies[k.as_str().unwrap()] = format!("{}", kv[index]).into();
}
}
}
}
_ => {}
}
true
}).unwrap();
transfer.read_function(|data| {
Ok(self.body.as_bytes().read(data).unwrap())
}).unwrap();
transfer.write_function(|data| {
body.extend_from_slice(data.clone());
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
self._state();
let data = String::from_utf8_lossy(&body);
let data = &data as &str;
match self.res_headers["type"].as_str().unwrap() {
"json" => {
return json::parse(data).unwrap();
}
"text" => {
return JsonValue::from(data);
}
"jpeg" => {
file::create_dir(self.filepath.as_str());
let mut file = File::create(self.filepath.as_str()).unwrap();
file.write(&body).unwrap();
let res = files::file::is_file(self.filepath.as_str());
return JsonValue::Boolean(res);
}
_ => {
println!("{:#}", self.res_headers);
}
}
return object! {};
}
fn _state(&mut self) {
self.res_headers["code"] = self.curl.response_code().unwrap().into();
self.res_headers["content-type"] = self.curl.content_type().unwrap().into();
let data = tools::string::split(self.res_headers["content-type"].to_string(), ";");
match data[0].as_str().unwrap() {
"application/json" => {
self.res_headers["type"] = "json".into();
}
"text/html" => {
self.res_headers["type"] = "text".into();
}
"image/jpeg" => {
self.res_headers["type"] = "jpeg".into();
}
_ => {
println!("{:#}", data);
self.res_headers["type"] = "text".into();
}
}
}
}