writium/
error.rs

1use std::fmt::{Display, Formatter, Result as FormatResult};
2use proto::HyperResponse;
3use prelude::*;
4use self::header::Header;
5
6/// Writium error.
7///
8/// # Error Handling
9///
10/// `Error` is another form of response in Writium Framework, i.e., it itself
11/// can be transformed into a response. It provides (hopefully) useful
12/// information about the error occured in the current transaction. The error
13/// types are customizable. Error types are defined as HTTP status codes
14/// (>= 400). Every error realized by Writium will be logged.
15pub struct Error {
16    headers: Headers,
17    status: StatusCode,
18    description: &'static str,
19    cause: Option<Box<::std::error::Error>>,
20}
21impl Error {
22    pub fn new(status: StatusCode, description: &'static str) -> Error {
23        Error {
24            status: status,
25            headers: Headers::default(),
26            description: description,
27            cause: None,
28        }
29    }
30    pub fn status(&self) -> StatusCode {
31        self.status
32    }
33
34    pub fn internal(description: &'static str) -> Error {
35        Error::new(StatusCode::InternalServerError, description)
36    }
37    pub fn unauthorized(description: &'static str) -> Error {
38        Error::new(StatusCode::Unauthorized, description)
39    }
40    pub fn bad_request(description: &'static str) -> Error {
41        Error::new(StatusCode::BadRequest, description)
42    }
43    pub fn forbidden(description: &'static str) -> Error {
44        Error::new(StatusCode::Forbidden, description)
45    }
46    pub fn not_found(description: &'static str) -> Error {
47        Error::new(StatusCode::NotFound, description)
48    }
49    pub fn method_not_allowed() -> Error {
50        Error::new(StatusCode::NotFound, "Method is not allowed.")
51    }
52
53    pub fn set_header<H: Header>(&mut self, header: H) {
54        self.headers.set(header);
55    }
56    pub fn set_headers(&mut self, headers: Headers) {
57        self.headers = headers;
58    }
59    pub fn set_cause<E>(&mut self, err: E)
60        where E: 'static + ::std::error::Error {
61        self.cause = Some(Box::new(err));
62    }
63    
64
65    pub fn with_header<H: Header>(mut self, header: H) -> Self {
66        self.headers.set(header);
67        self
68    }
69    pub fn with_headers(mut self, headers: Headers) -> Self {
70        self.headers = headers;
71        self
72    }
73    pub fn with_cause<E>(mut self, err: E) -> Self
74        where E: 'static + ::std::error::Error {
75        self.cause = Some(Box::new(err));
76        self
77    }
78}
79impl ::std::fmt::Debug for Error {
80    fn fmt(&self, f: &mut Formatter) -> FormatResult {
81        f.write_str(self.description)
82    }
83}
84impl Display for Error {
85    fn fmt(&self, f: &mut Formatter) -> FormatResult {
86        f.write_str(self.description)
87    }
88}
89impl ::std::error::Error for Error {
90    fn description(&self) -> &str {
91        self.description
92    }
93    fn cause(&self) -> Option<&::std::error::Error> {
94        match self.cause {
95            Some(ref e) => Some(&**e),
96            None => ::std::option::Option::None,
97        }
98    }
99}
100impl Into<HyperResponse> for Error {
101    fn into(self) -> HyperResponse {
102        use hyper::header::{ContentType, ContentLength};
103        let body = format!(r#"{{"msg":"{}"}}"#, self.description).into_bytes();
104        HyperResponse::new()
105            .with_status(self.status)
106            .with_headers(self.headers)
107            .with_header(ContentType("application/json; charset=UTF-8".parse().unwrap()))
108            .with_header(ContentLength(body.len() as u64))
109            .with_body(body)
110    }
111}
112
113pub type Result<T> = ::std::result::Result<T, Error>;