use std::fmt;
use url::Url;
use crate::error;
use crate::response::raw_response::RawResponse;
use crate::types::{Cookie, Header, RoUrl};
#[derive(Clone)]
pub struct Response {
raw: RawResponse
}
impl Response {
pub fn new(url: RoUrl, binary: Vec<u8>) -> error::Result<Self> {
Ok(Self {
raw: RawResponse::new(url, binary)?
})
}
}
impl Response {
pub fn ok(&self) -> bool {
self.code() == 200
}
pub fn is_redirect(&self) -> bool {
self.code() == 301 ||
self.code() == 302 ||
self.code() == 303 ||
self.code() == 307 ||
self.header_value("Location").is_some()
}
pub fn code(&self) -> u32 {
self.raw.code_get()
}
pub fn version(&self) -> &String {
self.raw.version_get()
}
pub fn reason(&self) -> &String {
self.raw.reason_get()
}
fn url(&self) -> &Url {
self.raw.url_get()
}
pub fn host(&self) -> &str {
self.url().host_str().unwrap_or_default()
}
pub fn body(&self) -> &ResponseBody {
self.raw.body_get()
}
pub fn binary(&self) -> &[u8] {
self.raw.binary_get()
}
pub fn location(&self) -> Option<&String> {
self.header_value("location")
}
pub fn headers(&self) -> &Vec<Header> {
self.raw.headers_get()
}
pub fn headers_of_name<S: AsRef<str>>(&self, name: S) -> Vec<&Header> {
self.headers().iter()
.filter(|header| header.name().eq_ignore_ascii_case(name.as_ref()))
.collect()
}
pub fn header<S: AsRef<str>>(&self, name: S) -> Option<&Header> {
self.headers().iter()
.find(|header| header.name().eq_ignore_ascii_case(name.as_ref()))
}
pub fn header_values<S: AsRef<str>>(&self, name: S) -> Vec<&String> {
self.headers().iter()
.filter(|header| header.name().eq_ignore_ascii_case(name.as_ref()))
.map(|header| header.value())
.collect()
}
pub fn header_value<S: AsRef<str>>(&self, name: S) -> Option<&String> {
self.header(name).map(|header| header.value())
}
pub fn cookies(&self) -> &Vec<Cookie> {
self.raw.cookies_get()
}
pub fn cookie<S: AsRef<str>>(&self, name: S) -> Option<&Cookie> {
self.cookies().iter().find(|cookie| cookie.name().eq_ignore_ascii_case(name.as_ref()))
}
}
impl fmt::Debug for Response {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.raw, formatter)
}
}
impl fmt::Display for Response {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.raw, formatter)
}
}
#[derive(Clone)]
pub struct ResponseBody {
binary: Vec<u8>
}
impl ResponseBody {
pub fn new(binary: Vec<u8>) -> Self {
Self { binary }
}
pub fn binary(&self) -> &[u8] {
self.binary.as_slice()
}
pub fn string(&self) -> error::Result<String> {
String::from_utf8(self.binary.clone()).map_err(error::body)
}
}
impl fmt::Debug for ResponseBody {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.string() {
Ok(text) => fmt::Debug::fmt(&text, formatter),
Err(e) => fmt::Debug::fmt(&e, formatter),
}
}
}
impl fmt::Display for ResponseBody {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.string() {
Ok(text) => fmt::Display::fmt(&text, formatter),
Err(e) => fmt::Display::fmt(&e, formatter),
}
}
}