nickel/
nickel_error.rs

1use std::borrow::Cow;
2use hyper::status::StatusCode;
3use std::io;
4use std::error::Error;
5use response::Response;
6use hyper::net::{Fresh, Streaming};
7
8/// NickelError is the basic error type for HTTP errors as well as user defined errors.
9/// One can pattern match against the `kind` property to handle the different cases.
10pub struct NickelError<'a, D: 'a = ()> {
11    pub stream: Option<Response<'a, D, Streaming>>,
12    pub message: Cow<'static, str>
13}
14
15impl<'a, D> NickelError<'a, D> {
16    /// Creates a new `NickelError` instance.
17    ///
18    /// You should probably use `Response#error` in favor of this.
19    ///
20    /// # Examples
21    /// ```{rust}
22    /// # extern crate nickel;
23    ///
24    /// # fn main() {
25    /// use nickel::{Request, Response, MiddlewareResult, NickelError};
26    /// use nickel::status::StatusCode;
27    ///
28    /// # #[allow(dead_code)]
29    /// fn handler<'a, D>(_: &mut Request<D>, res: Response<'a, D>) -> MiddlewareResult<'a, D> {
30    ///     Err(NickelError::new(res, "Error Parsing JSON", StatusCode::BadRequest))
31    /// }
32    /// # }
33    /// ```
34    pub fn new<T>(mut stream: Response<'a, D, Fresh>,
35                  message: T,
36                  status_code: StatusCode) -> NickelError<'a, D>
37            where T: Into<Cow<'static, str>> {
38        stream.set(status_code);
39
40        match stream.start() {
41            Ok(stream) =>
42                NickelError {
43                    stream: Some(stream),
44                    message: message.into(),
45                },
46            Err(e) => e
47        }
48    }
49
50    /// Creates a new `NickelError` without a `Response`.
51    ///
52    /// This should only be called in a state where the `Response` has
53    /// failed in an unrecoverable state. If there is an available
54    /// `Response` then it must be provided to `new` so that the
55    /// underlying stream can be flushed, allowing future requests.
56    ///
57    /// This is considered `unsafe` as deadlock can occur if the `Response`
58    /// does not have the underlying stream flushed when processing is finished.
59    pub unsafe fn without_response<T>(message: T) -> NickelError<'a, D>
60            where T: Into<Cow<'static, str>> {
61        NickelError {
62            stream: None,
63            message: message.into(),
64        }
65    }
66
67    pub fn end(self) -> Option<io::Result<()>> {
68        self.stream.map(|s| s.end())
69    }
70}
71
72impl<'a, T, D> From<(Response<'a, D>, (StatusCode, T))> for NickelError<'a, D>
73        where T: Into<Box<Error + 'static>> {
74    fn from((res, (errorcode, err)): (Response<'a, D>, (StatusCode, T))) -> NickelError<'a, D> {
75        let err = err.into();
76        NickelError::new(res, err.description().to_string(), errorcode)
77    }
78}
79
80impl<'a, D> From<(Response<'a, D>, String)> for NickelError<'a, D> {
81    fn from((res, msg): (Response<'a, D>, String)) -> NickelError<'a, D> {
82        NickelError::new(res, msg, StatusCode::InternalServerError)
83    }
84}
85
86impl<'a, D> From<(Response<'a, D>, StatusCode)> for NickelError<'a, D> {
87    fn from((res, code): (Response<'a, D>, StatusCode)) -> NickelError<'a, D> {
88        NickelError::new(res, "", code)
89    }
90}