use serde::{Deserialize, Serialize};
use serde::de::DeserializeOwned;
use hyper::header::Header;
use super::{Headers, StatusCode};
use error::{Error, Result};
pub use hyper::Response as HyperResponse;
#[derive(Debug)]
pub struct Response {
status: StatusCode,
headers: Headers,
body: Vec<u8>,
}
impl Response {
pub fn new() -> Self {
Response {
status: StatusCode::Ok,
headers: Headers::new(),
body: Vec::new(),
}
}
pub fn status(&self) -> StatusCode {
self.status.clone()
}
pub fn header<H: Header>(&self) -> Option<&H> {
self.headers.get::<H>()
}
pub fn body(&self) -> &[u8] {
&self.body
}
pub fn to_str(&self) -> Result<&str> {
::std::str::from_utf8(&self.body)
.map_err(|e| Error::internal("Unable to parse body as string.").with_cause(e))
}
pub fn to_json<T: 'static + DeserializeOwned>(&self) -> Result<T> {
use hyper::header::ContentType;
if let Some(&ContentType(ref ty)) = self.headers.get::<ContentType>() {
if ty.type_() != "application" || ty.subtype() != "json" {
let err = Error::bad_request("Content should be of type `application/json`.");
return Err(err)
}
}
::serde_json::from_slice::<T>(&self.body)
.map_err(|e| Error::internal("Unable to deserialize body as JSON.").with_cause(e))
}
pub fn to_form<'de, T: Deserialize<'de>>(&'de self) -> Result<T> {
use hyper::header::ContentType;
if let Some(&ContentType(ref ty)) = self.headers.get::<ContentType>() {
if ty.type_() != "application" || ty.subtype() != "x-www-form-urlencoded" {
let err = Error::bad_request("Content should be of type `application/x-www-form-urlencoded`.");
return Err(err)
}
}
::serde_qs::from_bytes(&self.body)
.map_err(|e| Error::internal("Unable to parse body as form data.").with_cause(e))
}
pub fn set_status(&mut self, status: StatusCode) {
self.status = status;
}
pub fn set_header<H: Header>(&mut self, header: H) {
self.headers.set(header);
}
pub fn set_headers(&mut self, headers: Headers) {
self.headers = headers;
}
pub fn set_body<B>(&mut self, body: B) where B: Into<Vec<u8>> {
self.body = body.into();
}
pub fn set_json<T: Serialize>(&mut self, json: &T) -> Result<()> {
use hyper::header::ContentType;
::serde_json::to_vec(&json)
.map(|json| {
self.body = json;
self.headers.set(ContentType("application/json; charset=UTF-8".parse().unwrap()));
})
.map_err(|err| Error::internal("Unable to serialize data into JSON.").with_cause(err))
}
pub fn with_status(mut self, status: StatusCode) -> Self {
self.status = status;
self
}
pub fn with_header<H: Header>(mut self, header: H) -> Self {
self.headers.set(header);
self
}
pub fn with_headers(mut self, headers: Headers) -> Self {
self.headers = headers;
self
}
pub fn with_body<B>(mut self, body: B) -> Self
where B: Into<Vec<u8>> {
self.body = body.into();
self
}
pub fn with_json<T: Serialize>(mut self, json: &T) -> Result<Self> {
self.set_json(json)
.map(|_| { self })
}
}
impl From<Response> for HyperResponse {
fn from(res: Response) -> HyperResponse {
let Response { status, headers, body } = res;
HyperResponse::new()
.with_status(status)
.with_headers(headers)
.with_body(body)
}
}