use bytes::Bytes;
use reqwest::header::HeaderMap;
use std::time::Duration;
pub(crate) enum ResponseBody {
Text(String),
Bytes(Bytes),
}
pub struct Response {
pub(super) url: String,
pub(super) status: u16,
pub(super) headers: HeaderMap,
pub(super) elapsed: Duration,
pub(crate) body: ResponseBody,
}
impl Response {
pub fn from_parts(url: impl Into<String>, status: u16, body: impl Into<String>) -> Self {
Self {
url: url.into(),
status,
headers: HeaderMap::new(),
elapsed: Duration::ZERO,
body: ResponseBody::Text(body.into()),
}
}
pub fn from_parts_with_headers(
url: impl Into<String>,
status: u16,
headers: HeaderMap,
body: impl Into<String>,
) -> Self {
Self {
url: url.into(),
status,
headers,
elapsed: Duration::ZERO,
body: ResponseBody::Text(body.into()),
}
}
pub fn with_elapsed(mut self, elapsed: Duration) -> Self {
self.elapsed = elapsed;
self
}
pub(crate) fn new(
url: String,
status: u16,
headers: HeaderMap,
elapsed: Duration,
body: ResponseBody,
) -> Self {
Self {
url,
status,
headers,
elapsed,
body,
}
}
pub fn from_file(
url: impl Into<String>,
path: impl AsRef<std::path::Path>,
) -> Result<Self, std::io::Error> {
let body = std::fs::read_to_string(path)?;
Ok(Self::from_parts(url, 200, body))
}
pub fn from_bytes(url: impl Into<String>, status: u16, bytes: Bytes) -> Self {
Self {
url: url.into(),
status,
headers: HeaderMap::new(),
elapsed: Duration::ZERO,
body: ResponseBody::Bytes(bytes),
}
}
pub fn url(&self) -> &str {
&self.url
}
pub fn status(&self) -> u16 {
self.status
}
pub fn headers(&self) -> &HeaderMap {
&self.headers
}
pub fn elapsed(&self) -> Duration {
self.elapsed
}
pub fn text(&self) -> Option<&str> {
match &self.body {
ResponseBody::Text(s) => Some(s.as_str()),
ResponseBody::Bytes(_) => None,
}
}
pub fn bytes(&self) -> &[u8] {
match &self.body {
ResponseBody::Text(s) => s.as_bytes(),
ResponseBody::Bytes(b) => b.as_ref(),
}
}
}