use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use serde_json::json;
use serde::Serialize;
use crate::error::{Error, Result};
#[derive(Debug, Serialize)]
pub struct Response {
status: u16,
success: bool,
url: String,
headers: HashMap<String, String>,
pub data: serde_json::Value,
pub objects: Vec<serde_json::Value>,
}
impl Response {
pub(crate) fn new() -> Response {
Response {
status: 200,
success: true,
url: String::with_capacity(50),
headers: HashMap::new(),
data: json!({}),
objects: Vec::new(),
}
}
pub(crate) fn set(reqwest_response: &mut reqwest::Response) -> Result<Response> {
let mut res = Response::new();
res.status = reqwest_response.status().as_u16();
if res.is_success() {
res.success = true;
}
else {
res.success = false;
}
res.url = reqwest_response.url().to_string();
res.data = match reqwest_response.json() {
Ok(t) => t,
Err(e) => {
let msg = format!("Response body received is not valid JSON. \
Error code: {}, message: {}", res.status(), e);
return Err(Error::Custom(msg));
}
};
let reqwest_headers = reqwest_response.headers();
let mut map = HashMap::new();
for (k, v) in reqwest_headers.iter() {
let k = k.as_str().to_string();
let v = v.to_str()?;
let v = v.to_string();
map.insert(k, v);
}
res.headers = map;
Ok(res)
}
pub(crate) fn check_tasks_status(res: &mut Response) {
if res.data["tasks"].is_array() {
for task in res.data["tasks"].as_array().unwrap() {
if task["status"] == "failed" || task["status"] == "partially succeeded" {
res.success = false;
}
}
}
}
pub fn status(&self) -> u16 {
self.status
}
pub fn is_informational(&self) -> bool {
self.status >= 100 && self.status < 200
}
pub fn is_success(&self) -> bool {
self.status >= 200 && self.status < 300 && self.success == true
}
pub fn is_not_success(&self) -> bool {
self.status < 200 || self.status >= 300 || self.success == false
}
pub fn is_redirection(&self) -> bool {
self.status >= 300 && self.status < 400
}
pub fn is_client_error(&self) -> bool {
self.status >= 400 && self.status < 500
}
pub fn is_server_error(&self) -> bool {
self.status >= 500 && self.status < 600
}
pub fn url(&self) -> &str {
self.url.as_str()
}
pub fn headers(&self) -> HashMap<String, String> {
self.headers.clone()
}
pub fn save_data(&self, file: &str) -> Result<()> {
let mut f = File::create(file)?;
let buf = Vec::new();
let formatter = serde_json::ser::PrettyFormatter::with_indent(b" ");
let mut ser = serde_json::Serializer::with_formatter(buf, formatter);
self.data.serialize(&mut ser)?;
f.write_all(&ser.into_inner())?;
Ok(())
}
pub fn save_objects(&self, file: &str) -> Result<()> {
let mut f = File::create(file)?;
let buf = Vec::new();
let formatter = serde_json::ser::PrettyFormatter::with_indent(b" ");
let mut ser = serde_json::Serializer::with_formatter(buf, formatter);
self.objects.serialize(&mut ser)?;
f.write_all(&ser.into_inner())?;
Ok(())
}
}