use crate::error::*;
use crate::http::types::{HttpData, ResponseMetadata};
use reqwest::Request;
use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::{HashMap, VecDeque};
use std::fs::File;
use std::io::Write;
use std::path::Path;
#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RecordedRequest {
pub method: String,
pub url: String,
pub headers: HashMap<String, Vec<HttpData>>,
pub body: Option<String>,
}
impl<'a> From<&'a Request> for RecordedRequest {
fn from(req: &'a Request) -> Self {
let mut headers = HashMap::new();
for (name, value) in req.headers().iter() {
let value: HttpData = match value.to_str() {
Ok(s) => HttpData::Text(s.to_owned()),
Err(_) => HttpData::Binary(value.as_bytes().to_vec()),
};
let entry = headers
.entry(name.as_str().to_owned())
.or_insert_with(Vec::new);
(*entry).push(value);
}
RecordedRequest {
method: req.method().to_string(),
url: req.url().as_str().to_owned(),
headers: headers,
body: req.body().map(|b| format!("{:?}", b)),
}
}
}
#[derive(Deserialize, Serialize)]
pub struct RecordedResponse {
pub metadata: ResponseMetadata,
pub body: HttpData,
}
impl<'a> From<&'a (ResponseMetadata, Vec<u8>)> for RecordedResponse {
fn from(res: &'a (ResponseMetadata, Vec<u8>)) -> Self {
RecordedResponse {
metadata: res.0.clone(),
body: HttpData::from(res.1.as_slice()),
}
}
}
#[derive(Deserialize, Serialize)]
pub struct RecordingEntry {
pub req: RecordedRequest,
pub res: RecordedResponse,
}
#[derive(Deserialize, Serialize)]
pub struct Recording(pub VecDeque<RecordingEntry>);
impl Recording {
pub fn flush<P: AsRef<Path>>(&self, output: P) -> Result<()> {
let mut f = File::create(output)?;
serde_json::to_writer_pretty(&mut f, self)?;
f.flush()?;
Ok(())
}
}
impl Default for Recording {
fn default() -> Self {
Recording(VecDeque::new())
}
}