use serde;
use serde_json;
use std::error;
use std::fmt;
use std::io::Error as IoError;
use Request;
#[derive(Debug)]
pub enum JsonError {
BodyAlreadyExtracted,
WrongContentType,
IoError(IoError),
ParseError(serde_json::Error),
}
impl From<IoError> for JsonError {
fn from(err: IoError) -> JsonError {
JsonError::IoError(err)
}
}
impl From<serde_json::Error> for JsonError {
fn from(err: serde_json::Error) -> JsonError {
JsonError::ParseError(err)
}
}
impl error::Error for JsonError {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
JsonError::IoError(ref e) => Some(e),
JsonError::ParseError(ref e) => Some(e),
_ => None,
}
}
}
impl fmt::Display for JsonError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let description = match *self {
JsonError::BodyAlreadyExtracted => "the body of the request was already extracted",
JsonError::WrongContentType => "the request didn't have a JSON content type",
JsonError::IoError(_) => {
"could not read the body from the request, or could not execute the CGI program"
}
JsonError::ParseError(_) => "error while parsing the JSON body",
};
write!(fmt, "{}", description)
}
}
pub fn json_input<O>(request: &Request) -> Result<O, JsonError>
where
O: serde::de::DeserializeOwned,
{
if let Some(header) = request.header("Content-Type") {
if !header.starts_with("application/json") {
return Err(JsonError::WrongContentType);
}
} else {
return Err(JsonError::WrongContentType);
}
if let Some(b) = request.data() {
serde_json::from_reader::<_, O>(b).map_err(From::from)
} else {
Err(JsonError::BodyAlreadyExtracted)
}
}