requiem_http/
error.rs

1//! Error and Result module
2use std::any::TypeId;
3use std::cell::RefCell;
4use std::io::Write;
5use std::str::Utf8Error;
6use std::string::FromUtf8Error;
7use std::{fmt, io, result};
8
9use requiem_codec::{Decoder, Encoder};
10pub use requiem_threadpool::BlockingError;
11use requiem_utils::framed::DispatcherError as FramedDispatcherError;
12use requiem_utils::timeout::TimeoutError;
13use bytes::BytesMut;
14use derive_more::{Display, From};
15pub use futures_channel::oneshot::Canceled;
16use http::uri::InvalidUri;
17use http::{header, Error as HttpError, StatusCode};
18use httparse;
19use serde::de::value::Error as DeError;
20use serde_json::error::Error as JsonError;
21use serde_urlencoded::ser::Error as FormError;
22
23// re-export for convinience
24use crate::body::Body;
25pub use crate::cookie::ParseError as CookieParseError;
26use crate::helpers::Writer;
27use crate::response::{Response, ResponseBuilder};
28
29/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
30/// for actix web operations
31///
32/// This typedef is generally used to avoid writing out
33/// `requiem_http::error::Error` directly and is otherwise a direct mapping to
34/// `Result`.
35pub type Result<T, E = Error> = result::Result<T, E>;
36
37/// General purpose actix web error.
38///
39/// An actix web error is used to carry errors from `failure` or `std::error`
40/// through actix in a convenient way.  It can be created through
41/// converting errors with `into()`.
42///
43/// Whenever it is created from an external object a response error is created
44/// for it that can be used to create an http response from it this means that
45/// if you have access to an actix `Error` you can always get a
46/// `ResponseError` reference from it.
47pub struct Error {
48    cause: Box<dyn ResponseError>,
49}
50
51impl Error {
52    /// Returns the reference to the underlying `ResponseError`.
53    pub fn as_response_error(&self) -> &dyn ResponseError {
54        self.cause.as_ref()
55    }
56
57    /// Similar to `as_response_error` but downcasts.
58    pub fn as_error<T: ResponseError + 'static>(&self) -> Option<&T> {
59        ResponseError::downcast_ref(self.cause.as_ref())
60    }
61}
62
63/// Error that can be converted to `Response`
64pub trait ResponseError: fmt::Debug + fmt::Display {
65    /// Response's status code
66    ///
67    /// Internal server error is generated by default.
68    fn status_code(&self) -> StatusCode {
69        StatusCode::INTERNAL_SERVER_ERROR
70    }
71
72    /// Create response for error
73    ///
74    /// Internal server error is generated by default.
75    fn error_response(&self) -> Response {
76        let mut resp = Response::new(self.status_code());
77        let mut buf = BytesMut::new();
78        let _ = write!(Writer(&mut buf), "{}", self);
79        resp.headers_mut().insert(
80            header::CONTENT_TYPE,
81            header::HeaderValue::from_static("text/plain; charset=utf-8"),
82        );
83        resp.set_body(Body::from(buf))
84    }
85
86    #[doc(hidden)]
87    fn __private_get_type_id__(&self) -> TypeId
88    where
89        Self: 'static,
90    {
91        TypeId::of::<Self>()
92    }
93}
94
95impl dyn ResponseError + 'static {
96    /// Downcasts a response error to a specific type.
97    pub fn downcast_ref<T: ResponseError + 'static>(&self) -> Option<&T> {
98        if self.__private_get_type_id__() == TypeId::of::<T>() {
99            unsafe { Some(&*(self as *const dyn ResponseError as *const T)) }
100        } else {
101            None
102        }
103    }
104}
105
106impl fmt::Display for Error {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        fmt::Display::fmt(&self.cause, f)
109    }
110}
111
112impl fmt::Debug for Error {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        write!(f, "{:?}", &self.cause)
115    }
116}
117
118impl std::error::Error for Error {
119    fn cause(&self) -> Option<&dyn std::error::Error> {
120        None
121    }
122
123    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
124        None
125    }
126}
127
128impl From<()> for Error {
129    fn from(_: ()) -> Self {
130        Error::from(UnitError)
131    }
132}
133
134impl From<std::convert::Infallible> for Error {
135    fn from(_: std::convert::Infallible) -> Self {
136        // `std::convert::Infallible` indicates an error
137        // that will never happen
138        unreachable!()
139    }
140}
141
142/// Convert `Error` to a `Response` instance
143impl From<Error> for Response {
144    fn from(err: Error) -> Self {
145        Response::from_error(err)
146    }
147}
148
149/// `Error` for any error that implements `ResponseError`
150impl<T: ResponseError + 'static> From<T> for Error {
151    fn from(err: T) -> Error {
152        Error {
153            cause: Box::new(err),
154        }
155    }
156}
157
158/// Convert Response to a Error
159impl From<Response> for Error {
160    fn from(res: Response) -> Error {
161        InternalError::from_response("", res).into()
162    }
163}
164
165/// Convert ResponseBuilder to a Error
166impl From<ResponseBuilder> for Error {
167    fn from(mut res: ResponseBuilder) -> Error {
168        InternalError::from_response("", res.finish()).into()
169    }
170}
171
172/// Return `GATEWAY_TIMEOUT` for `TimeoutError`
173impl<E: ResponseError> ResponseError for TimeoutError<E> {
174    fn status_code(&self) -> StatusCode {
175        match self {
176            TimeoutError::Service(e) => e.status_code(),
177            TimeoutError::Timeout => StatusCode::GATEWAY_TIMEOUT,
178        }
179    }
180}
181
182#[derive(Debug, Display)]
183#[display(fmt = "UnknownError")]
184struct UnitError;
185
186/// `InternalServerError` for `UnitError`
187impl ResponseError for UnitError {}
188
189/// `InternalServerError` for `JsonError`
190impl ResponseError for JsonError {}
191
192/// `InternalServerError` for `FormError`
193impl ResponseError for FormError {}
194
195#[cfg(feature = "openssl")]
196/// `InternalServerError` for `openssl::ssl::Error`
197impl ResponseError for requiem_connect::ssl::openssl::SslError {}
198
199#[cfg(feature = "openssl")]
200/// `InternalServerError` for `openssl::ssl::HandshakeError`
201impl<T: std::fmt::Debug> ResponseError for requiem_tls::openssl::HandshakeError<T> {}
202
203/// Return `BAD_REQUEST` for `de::value::Error`
204impl ResponseError for DeError {
205    fn status_code(&self) -> StatusCode {
206        StatusCode::BAD_REQUEST
207    }
208}
209
210/// `InternalServerError` for `Canceled`
211impl ResponseError for Canceled {}
212
213/// `InternalServerError` for `BlockingError`
214impl<E: fmt::Debug> ResponseError for BlockingError<E> {}
215
216/// Return `BAD_REQUEST` for `Utf8Error`
217impl ResponseError for Utf8Error {
218    fn status_code(&self) -> StatusCode {
219        StatusCode::BAD_REQUEST
220    }
221}
222
223/// Return `InternalServerError` for `HttpError`,
224/// Response generation can return `HttpError`, so it is internal error
225impl ResponseError for HttpError {}
226
227/// Return `InternalServerError` for `io::Error`
228impl ResponseError for io::Error {
229    fn status_code(&self) -> StatusCode {
230        match self.kind() {
231            io::ErrorKind::NotFound => StatusCode::NOT_FOUND,
232            io::ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
233            _ => StatusCode::INTERNAL_SERVER_ERROR,
234        }
235    }
236}
237
238/// `BadRequest` for `InvalidHeaderValue`
239impl ResponseError for header::InvalidHeaderValue {
240    fn status_code(&self) -> StatusCode {
241        StatusCode::BAD_REQUEST
242    }
243}
244
245/// A set of errors that can occur during parsing HTTP streams
246#[derive(Debug, Display)]
247pub enum ParseError {
248    /// An invalid `Method`, such as `GE.T`.
249    #[display(fmt = "Invalid Method specified")]
250    Method,
251    /// An invalid `Uri`, such as `exam ple.domain`.
252    #[display(fmt = "Uri error: {}", _0)]
253    Uri(InvalidUri),
254    /// An invalid `HttpVersion`, such as `HTP/1.1`
255    #[display(fmt = "Invalid HTTP version specified")]
256    Version,
257    /// An invalid `Header`.
258    #[display(fmt = "Invalid Header provided")]
259    Header,
260    /// A message head is too large to be reasonable.
261    #[display(fmt = "Message head is too large")]
262    TooLarge,
263    /// A message reached EOF, but is not complete.
264    #[display(fmt = "Message is incomplete")]
265    Incomplete,
266    /// An invalid `Status`, such as `1337 ELITE`.
267    #[display(fmt = "Invalid Status provided")]
268    Status,
269    /// A timeout occurred waiting for an IO event.
270    #[allow(dead_code)]
271    #[display(fmt = "Timeout")]
272    Timeout,
273    /// An `io::Error` that occurred while trying to read or write to a network
274    /// stream.
275    #[display(fmt = "IO error: {}", _0)]
276    Io(io::Error),
277    /// Parsing a field as string failed
278    #[display(fmt = "UTF8 error: {}", _0)]
279    Utf8(Utf8Error),
280}
281
282/// Return `BadRequest` for `ParseError`
283impl ResponseError for ParseError {
284    fn status_code(&self) -> StatusCode {
285        StatusCode::BAD_REQUEST
286    }
287}
288
289impl From<io::Error> for ParseError {
290    fn from(err: io::Error) -> ParseError {
291        ParseError::Io(err)
292    }
293}
294
295impl From<InvalidUri> for ParseError {
296    fn from(err: InvalidUri) -> ParseError {
297        ParseError::Uri(err)
298    }
299}
300
301impl From<Utf8Error> for ParseError {
302    fn from(err: Utf8Error) -> ParseError {
303        ParseError::Utf8(err)
304    }
305}
306
307impl From<FromUtf8Error> for ParseError {
308    fn from(err: FromUtf8Error) -> ParseError {
309        ParseError::Utf8(err.utf8_error())
310    }
311}
312
313impl From<httparse::Error> for ParseError {
314    fn from(err: httparse::Error) -> ParseError {
315        match err {
316            httparse::Error::HeaderName
317            | httparse::Error::HeaderValue
318            | httparse::Error::NewLine
319            | httparse::Error::Token => ParseError::Header,
320            httparse::Error::Status => ParseError::Status,
321            httparse::Error::TooManyHeaders => ParseError::TooLarge,
322            httparse::Error::Version => ParseError::Version,
323        }
324    }
325}
326
327#[derive(Display, Debug)]
328/// A set of errors that can occur during payload parsing
329pub enum PayloadError {
330    /// A payload reached EOF, but is not complete.
331    #[display(
332        fmt = "A payload reached EOF, but is not complete. With error: {:?}",
333        _0
334    )]
335    Incomplete(Option<io::Error>),
336    /// Content encoding stream corruption
337    #[display(fmt = "Can not decode content-encoding.")]
338    EncodingCorrupted,
339    /// A payload reached size limit.
340    #[display(fmt = "A payload reached size limit.")]
341    Overflow,
342    /// A payload length is unknown.
343    #[display(fmt = "A payload length is unknown.")]
344    UnknownLength,
345    /// Http2 payload error
346    #[display(fmt = "{}", _0)]
347    Http2Payload(h2::Error),
348    /// Io error
349    #[display(fmt = "{}", _0)]
350    Io(io::Error),
351}
352
353impl From<h2::Error> for PayloadError {
354    fn from(err: h2::Error) -> Self {
355        PayloadError::Http2Payload(err)
356    }
357}
358
359impl From<Option<io::Error>> for PayloadError {
360    fn from(err: Option<io::Error>) -> Self {
361        PayloadError::Incomplete(err)
362    }
363}
364
365impl From<io::Error> for PayloadError {
366    fn from(err: io::Error) -> Self {
367        PayloadError::Incomplete(Some(err))
368    }
369}
370
371impl From<BlockingError<io::Error>> for PayloadError {
372    fn from(err: BlockingError<io::Error>) -> Self {
373        match err {
374            BlockingError::Error(e) => PayloadError::Io(e),
375            BlockingError::Canceled => PayloadError::Io(io::Error::new(
376                io::ErrorKind::Other,
377                "Operation is canceled",
378            )),
379        }
380    }
381}
382
383/// `PayloadError` returns two possible results:
384///
385/// - `Overflow` returns `PayloadTooLarge`
386/// - Other errors returns `BadRequest`
387impl ResponseError for PayloadError {
388    fn status_code(&self) -> StatusCode {
389        match *self {
390            PayloadError::Overflow => StatusCode::PAYLOAD_TOO_LARGE,
391            _ => StatusCode::BAD_REQUEST,
392        }
393    }
394}
395
396/// Return `BadRequest` for `cookie::ParseError`
397impl ResponseError for crate::cookie::ParseError {
398    fn status_code(&self) -> StatusCode {
399        StatusCode::BAD_REQUEST
400    }
401}
402
403#[derive(Debug, Display, From)]
404/// A set of errors that can occur during dispatching http requests
405pub enum DispatchError {
406    /// Service error
407    Service(Error),
408
409    /// Upgrade service error
410    Upgrade,
411
412    /// An `io::Error` that occurred while trying to read or write to a network
413    /// stream.
414    #[display(fmt = "IO error: {}", _0)]
415    Io(io::Error),
416
417    /// Http request parse error.
418    #[display(fmt = "Parse error: {}", _0)]
419    Parse(ParseError),
420
421    /// Http/2 error
422    #[display(fmt = "{}", _0)]
423    H2(h2::Error),
424
425    /// The first request did not complete within the specified timeout.
426    #[display(fmt = "The first request did not complete within the specified timeout")]
427    SlowRequestTimeout,
428
429    /// Disconnect timeout. Makes sense for ssl streams.
430    #[display(fmt = "Connection shutdown timeout")]
431    DisconnectTimeout,
432
433    /// Payload is not consumed
434    #[display(fmt = "Task is completed but request's payload is not consumed")]
435    PayloadIsNotConsumed,
436
437    /// Malformed request
438    #[display(fmt = "Malformed request")]
439    MalformedRequest,
440
441    /// Internal error
442    #[display(fmt = "Internal error")]
443    InternalError,
444
445    /// Unknown error
446    #[display(fmt = "Unknown error")]
447    Unknown,
448}
449
450/// A set of error that can occure during parsing content type
451#[derive(PartialEq, Debug, Display)]
452pub enum ContentTypeError {
453    /// Can not parse content type
454    #[display(fmt = "Can not parse content type")]
455    ParseError,
456    /// Unknown content encoding
457    #[display(fmt = "Unknown content encoding")]
458    UnknownEncoding,
459}
460
461/// Return `BadRequest` for `ContentTypeError`
462impl ResponseError for ContentTypeError {
463    fn status_code(&self) -> StatusCode {
464        StatusCode::BAD_REQUEST
465    }
466}
467
468impl<E, U: Encoder + Decoder> ResponseError for FramedDispatcherError<E, U>
469where
470    E: fmt::Debug + fmt::Display,
471    <U as Encoder>::Error: fmt::Debug,
472    <U as Decoder>::Error: fmt::Debug,
473{
474}
475
476/// Helper type that can wrap any error and generate custom response.
477///
478/// In following example any `io::Error` will be converted into "BAD REQUEST"
479/// response as opposite to *INTERNAL SERVER ERROR* which is defined by
480/// default.
481///
482/// ```rust
483/// # use std::io;
484/// # use requiem_http::*;
485///
486/// fn index(req: Request) -> Result<&'static str> {
487///     Err(error::ErrorBadRequest(io::Error::new(io::ErrorKind::Other, "error")))
488/// }
489/// ```
490pub struct InternalError<T> {
491    cause: T,
492    status: InternalErrorType,
493}
494
495enum InternalErrorType {
496    Status(StatusCode),
497    Response(RefCell<Option<Response>>),
498}
499
500impl<T> InternalError<T> {
501    /// Create `InternalError` instance
502    pub fn new(cause: T, status: StatusCode) -> Self {
503        InternalError {
504            cause,
505            status: InternalErrorType::Status(status),
506        }
507    }
508
509    /// Create `InternalError` with predefined `Response`.
510    pub fn from_response(cause: T, response: Response) -> Self {
511        InternalError {
512            cause,
513            status: InternalErrorType::Response(RefCell::new(Some(response))),
514        }
515    }
516}
517
518impl<T> fmt::Debug for InternalError<T>
519where
520    T: fmt::Debug + 'static,
521{
522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523        fmt::Debug::fmt(&self.cause, f)
524    }
525}
526
527impl<T> fmt::Display for InternalError<T>
528where
529    T: fmt::Display + 'static,
530{
531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532        fmt::Display::fmt(&self.cause, f)
533    }
534}
535
536impl<T> ResponseError for InternalError<T>
537where
538    T: fmt::Debug + fmt::Display + 'static,
539{
540    fn status_code(&self) -> StatusCode {
541        match self.status {
542            InternalErrorType::Status(st) => st,
543            InternalErrorType::Response(ref resp) => {
544                if let Some(resp) = resp.borrow().as_ref() {
545                    resp.head().status
546                } else {
547                    StatusCode::INTERNAL_SERVER_ERROR
548                }
549            }
550        }
551    }
552
553    fn error_response(&self) -> Response {
554        match self.status {
555            InternalErrorType::Status(st) => {
556                let mut res = Response::new(st);
557                let mut buf = BytesMut::new();
558                let _ = write!(Writer(&mut buf), "{}", self);
559                res.headers_mut().insert(
560                    header::CONTENT_TYPE,
561                    header::HeaderValue::from_static("text/plain; charset=utf-8"),
562                );
563                res.set_body(Body::from(buf))
564            }
565            InternalErrorType::Response(ref resp) => {
566                if let Some(resp) = resp.borrow_mut().take() {
567                    resp
568                } else {
569                    Response::new(StatusCode::INTERNAL_SERVER_ERROR)
570                }
571            }
572        }
573    }
574}
575
576/// Helper function that creates wrapper of any error and generate *BAD
577/// REQUEST* response.
578#[allow(non_snake_case)]
579pub fn ErrorBadRequest<T>(err: T) -> Error
580where
581    T: fmt::Debug + fmt::Display + 'static,
582{
583    InternalError::new(err, StatusCode::BAD_REQUEST).into()
584}
585
586/// Helper function that creates wrapper of any error and generate
587/// *UNAUTHORIZED* response.
588#[allow(non_snake_case)]
589pub fn ErrorUnauthorized<T>(err: T) -> Error
590where
591    T: fmt::Debug + fmt::Display + 'static,
592{
593    InternalError::new(err, StatusCode::UNAUTHORIZED).into()
594}
595
596/// Helper function that creates wrapper of any error and generate
597/// *PAYMENT_REQUIRED* response.
598#[allow(non_snake_case)]
599pub fn ErrorPaymentRequired<T>(err: T) -> Error
600where
601    T: fmt::Debug + fmt::Display + 'static,
602{
603    InternalError::new(err, StatusCode::PAYMENT_REQUIRED).into()
604}
605
606/// Helper function that creates wrapper of any error and generate *FORBIDDEN*
607/// response.
608#[allow(non_snake_case)]
609pub fn ErrorForbidden<T>(err: T) -> Error
610where
611    T: fmt::Debug + fmt::Display + 'static,
612{
613    InternalError::new(err, StatusCode::FORBIDDEN).into()
614}
615
616/// Helper function that creates wrapper of any error and generate *NOT FOUND*
617/// response.
618#[allow(non_snake_case)]
619pub fn ErrorNotFound<T>(err: T) -> Error
620where
621    T: fmt::Debug + fmt::Display + 'static,
622{
623    InternalError::new(err, StatusCode::NOT_FOUND).into()
624}
625
626/// Helper function that creates wrapper of any error and generate *METHOD NOT
627/// ALLOWED* response.
628#[allow(non_snake_case)]
629pub fn ErrorMethodNotAllowed<T>(err: T) -> Error
630where
631    T: fmt::Debug + fmt::Display + 'static,
632{
633    InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED).into()
634}
635
636/// Helper function that creates wrapper of any error and generate *NOT
637/// ACCEPTABLE* response.
638#[allow(non_snake_case)]
639pub fn ErrorNotAcceptable<T>(err: T) -> Error
640where
641    T: fmt::Debug + fmt::Display + 'static,
642{
643    InternalError::new(err, StatusCode::NOT_ACCEPTABLE).into()
644}
645
646/// Helper function that creates wrapper of any error and generate *PROXY
647/// AUTHENTICATION REQUIRED* response.
648#[allow(non_snake_case)]
649pub fn ErrorProxyAuthenticationRequired<T>(err: T) -> Error
650where
651    T: fmt::Debug + fmt::Display + 'static,
652{
653    InternalError::new(err, StatusCode::PROXY_AUTHENTICATION_REQUIRED).into()
654}
655
656/// Helper function that creates wrapper of any error and generate *REQUEST
657/// TIMEOUT* response.
658#[allow(non_snake_case)]
659pub fn ErrorRequestTimeout<T>(err: T) -> Error
660where
661    T: fmt::Debug + fmt::Display + 'static,
662{
663    InternalError::new(err, StatusCode::REQUEST_TIMEOUT).into()
664}
665
666/// Helper function that creates wrapper of any error and generate *CONFLICT*
667/// response.
668#[allow(non_snake_case)]
669pub fn ErrorConflict<T>(err: T) -> Error
670where
671    T: fmt::Debug + fmt::Display + 'static,
672{
673    InternalError::new(err, StatusCode::CONFLICT).into()
674}
675
676/// Helper function that creates wrapper of any error and generate *GONE*
677/// response.
678#[allow(non_snake_case)]
679pub fn ErrorGone<T>(err: T) -> Error
680where
681    T: fmt::Debug + fmt::Display + 'static,
682{
683    InternalError::new(err, StatusCode::GONE).into()
684}
685
686/// Helper function that creates wrapper of any error and generate *LENGTH
687/// REQUIRED* response.
688#[allow(non_snake_case)]
689pub fn ErrorLengthRequired<T>(err: T) -> Error
690where
691    T: fmt::Debug + fmt::Display + 'static,
692{
693    InternalError::new(err, StatusCode::LENGTH_REQUIRED).into()
694}
695
696/// Helper function that creates wrapper of any error and generate
697/// *PAYLOAD TOO LARGE* response.
698#[allow(non_snake_case)]
699pub fn ErrorPayloadTooLarge<T>(err: T) -> Error
700where
701    T: fmt::Debug + fmt::Display + 'static,
702{
703    InternalError::new(err, StatusCode::PAYLOAD_TOO_LARGE).into()
704}
705
706/// Helper function that creates wrapper of any error and generate
707/// *URI TOO LONG* response.
708#[allow(non_snake_case)]
709pub fn ErrorUriTooLong<T>(err: T) -> Error
710where
711    T: fmt::Debug + fmt::Display + 'static,
712{
713    InternalError::new(err, StatusCode::URI_TOO_LONG).into()
714}
715
716/// Helper function that creates wrapper of any error and generate
717/// *UNSUPPORTED MEDIA TYPE* response.
718#[allow(non_snake_case)]
719pub fn ErrorUnsupportedMediaType<T>(err: T) -> Error
720where
721    T: fmt::Debug + fmt::Display + 'static,
722{
723    InternalError::new(err, StatusCode::UNSUPPORTED_MEDIA_TYPE).into()
724}
725
726/// Helper function that creates wrapper of any error and generate
727/// *RANGE NOT SATISFIABLE* response.
728#[allow(non_snake_case)]
729pub fn ErrorRangeNotSatisfiable<T>(err: T) -> Error
730where
731    T: fmt::Debug + fmt::Display + 'static,
732{
733    InternalError::new(err, StatusCode::RANGE_NOT_SATISFIABLE).into()
734}
735
736/// Helper function that creates wrapper of any error and generate
737/// *IM A TEAPOT* response.
738#[allow(non_snake_case)]
739pub fn ErrorImATeapot<T>(err: T) -> Error
740where
741    T: fmt::Debug + fmt::Display + 'static,
742{
743    InternalError::new(err, StatusCode::IM_A_TEAPOT).into()
744}
745
746/// Helper function that creates wrapper of any error and generate
747/// *MISDIRECTED REQUEST* response.
748#[allow(non_snake_case)]
749pub fn ErrorMisdirectedRequest<T>(err: T) -> Error
750where
751    T: fmt::Debug + fmt::Display + 'static,
752{
753    InternalError::new(err, StatusCode::MISDIRECTED_REQUEST).into()
754}
755
756/// Helper function that creates wrapper of any error and generate
757/// *UNPROCESSABLE ENTITY* response.
758#[allow(non_snake_case)]
759pub fn ErrorUnprocessableEntity<T>(err: T) -> Error
760where
761    T: fmt::Debug + fmt::Display + 'static,
762{
763    InternalError::new(err, StatusCode::UNPROCESSABLE_ENTITY).into()
764}
765
766/// Helper function that creates wrapper of any error and generate
767/// *LOCKED* response.
768#[allow(non_snake_case)]
769pub fn ErrorLocked<T>(err: T) -> Error
770where
771    T: fmt::Debug + fmt::Display + 'static,
772{
773    InternalError::new(err, StatusCode::LOCKED).into()
774}
775
776/// Helper function that creates wrapper of any error and generate
777/// *FAILED DEPENDENCY* response.
778#[allow(non_snake_case)]
779pub fn ErrorFailedDependency<T>(err: T) -> Error
780where
781    T: fmt::Debug + fmt::Display + 'static,
782{
783    InternalError::new(err, StatusCode::FAILED_DEPENDENCY).into()
784}
785
786/// Helper function that creates wrapper of any error and generate
787/// *UPGRADE REQUIRED* response.
788#[allow(non_snake_case)]
789pub fn ErrorUpgradeRequired<T>(err: T) -> Error
790where
791    T: fmt::Debug + fmt::Display + 'static,
792{
793    InternalError::new(err, StatusCode::UPGRADE_REQUIRED).into()
794}
795
796/// Helper function that creates wrapper of any error and generate
797/// *PRECONDITION FAILED* response.
798#[allow(non_snake_case)]
799pub fn ErrorPreconditionFailed<T>(err: T) -> Error
800where
801    T: fmt::Debug + fmt::Display + 'static,
802{
803    InternalError::new(err, StatusCode::PRECONDITION_FAILED).into()
804}
805
806/// Helper function that creates wrapper of any error and generate
807/// *PRECONDITION REQUIRED* response.
808#[allow(non_snake_case)]
809pub fn ErrorPreconditionRequired<T>(err: T) -> Error
810where
811    T: fmt::Debug + fmt::Display + 'static,
812{
813    InternalError::new(err, StatusCode::PRECONDITION_REQUIRED).into()
814}
815
816/// Helper function that creates wrapper of any error and generate
817/// *TOO MANY REQUESTS* response.
818#[allow(non_snake_case)]
819pub fn ErrorTooManyRequests<T>(err: T) -> Error
820where
821    T: fmt::Debug + fmt::Display + 'static,
822{
823    InternalError::new(err, StatusCode::TOO_MANY_REQUESTS).into()
824}
825
826/// Helper function that creates wrapper of any error and generate
827/// *REQUEST HEADER FIELDS TOO LARGE* response.
828#[allow(non_snake_case)]
829pub fn ErrorRequestHeaderFieldsTooLarge<T>(err: T) -> Error
830where
831    T: fmt::Debug + fmt::Display + 'static,
832{
833    InternalError::new(err, StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE).into()
834}
835
836/// Helper function that creates wrapper of any error and generate
837/// *UNAVAILABLE FOR LEGAL REASONS* response.
838#[allow(non_snake_case)]
839pub fn ErrorUnavailableForLegalReasons<T>(err: T) -> Error
840where
841    T: fmt::Debug + fmt::Display + 'static,
842{
843    InternalError::new(err, StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS).into()
844}
845
846/// Helper function that creates wrapper of any error and generate
847/// *EXPECTATION FAILED* response.
848#[allow(non_snake_case)]
849pub fn ErrorExpectationFailed<T>(err: T) -> Error
850where
851    T: fmt::Debug + fmt::Display + 'static,
852{
853    InternalError::new(err, StatusCode::EXPECTATION_FAILED).into()
854}
855
856/// Helper function that creates wrapper of any error and
857/// generate *INTERNAL SERVER ERROR* response.
858#[allow(non_snake_case)]
859pub fn ErrorInternalServerError<T>(err: T) -> Error
860where
861    T: fmt::Debug + fmt::Display + 'static,
862{
863    InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR).into()
864}
865
866/// Helper function that creates wrapper of any error and
867/// generate *NOT IMPLEMENTED* response.
868#[allow(non_snake_case)]
869pub fn ErrorNotImplemented<T>(err: T) -> Error
870where
871    T: fmt::Debug + fmt::Display + 'static,
872{
873    InternalError::new(err, StatusCode::NOT_IMPLEMENTED).into()
874}
875
876/// Helper function that creates wrapper of any error and
877/// generate *BAD GATEWAY* response.
878#[allow(non_snake_case)]
879pub fn ErrorBadGateway<T>(err: T) -> Error
880where
881    T: fmt::Debug + fmt::Display + 'static,
882{
883    InternalError::new(err, StatusCode::BAD_GATEWAY).into()
884}
885
886/// Helper function that creates wrapper of any error and
887/// generate *SERVICE UNAVAILABLE* response.
888#[allow(non_snake_case)]
889pub fn ErrorServiceUnavailable<T>(err: T) -> Error
890where
891    T: fmt::Debug + fmt::Display + 'static,
892{
893    InternalError::new(err, StatusCode::SERVICE_UNAVAILABLE).into()
894}
895
896/// Helper function that creates wrapper of any error and
897/// generate *GATEWAY TIMEOUT* response.
898#[allow(non_snake_case)]
899pub fn ErrorGatewayTimeout<T>(err: T) -> Error
900where
901    T: fmt::Debug + fmt::Display + 'static,
902{
903    InternalError::new(err, StatusCode::GATEWAY_TIMEOUT).into()
904}
905
906/// Helper function that creates wrapper of any error and
907/// generate *HTTP VERSION NOT SUPPORTED* response.
908#[allow(non_snake_case)]
909pub fn ErrorHttpVersionNotSupported<T>(err: T) -> Error
910where
911    T: fmt::Debug + fmt::Display + 'static,
912{
913    InternalError::new(err, StatusCode::HTTP_VERSION_NOT_SUPPORTED).into()
914}
915
916/// Helper function that creates wrapper of any error and
917/// generate *VARIANT ALSO NEGOTIATES* response.
918#[allow(non_snake_case)]
919pub fn ErrorVariantAlsoNegotiates<T>(err: T) -> Error
920where
921    T: fmt::Debug + fmt::Display + 'static,
922{
923    InternalError::new(err, StatusCode::VARIANT_ALSO_NEGOTIATES).into()
924}
925
926/// Helper function that creates wrapper of any error and
927/// generate *INSUFFICIENT STORAGE* response.
928#[allow(non_snake_case)]
929pub fn ErrorInsufficientStorage<T>(err: T) -> Error
930where
931    T: fmt::Debug + fmt::Display + 'static,
932{
933    InternalError::new(err, StatusCode::INSUFFICIENT_STORAGE).into()
934}
935
936/// Helper function that creates wrapper of any error and
937/// generate *LOOP DETECTED* response.
938#[allow(non_snake_case)]
939pub fn ErrorLoopDetected<T>(err: T) -> Error
940where
941    T: fmt::Debug + fmt::Display + 'static,
942{
943    InternalError::new(err, StatusCode::LOOP_DETECTED).into()
944}
945
946/// Helper function that creates wrapper of any error and
947/// generate *NOT EXTENDED* response.
948#[allow(non_snake_case)]
949pub fn ErrorNotExtended<T>(err: T) -> Error
950where
951    T: fmt::Debug + fmt::Display + 'static,
952{
953    InternalError::new(err, StatusCode::NOT_EXTENDED).into()
954}
955
956/// Helper function that creates wrapper of any error and
957/// generate *NETWORK AUTHENTICATION REQUIRED* response.
958#[allow(non_snake_case)]
959pub fn ErrorNetworkAuthenticationRequired<T>(err: T) -> Error
960where
961    T: fmt::Debug + fmt::Display + 'static,
962{
963    InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED).into()
964}
965
966#[cfg(feature = "failure")]
967/// Compatibility for `failure::Error`
968impl ResponseError for fail_ure::Error {}
969
970#[cfg(test)]
971mod tests {
972    use super::*;
973    use http::{Error as HttpError, StatusCode};
974    use httparse;
975    use std::io;
976
977    #[test]
978    fn test_into_response() {
979        let resp: Response = ParseError::Incomplete.error_response();
980        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
981
982        let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
983        let resp: Response = err.error_response();
984        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
985    }
986
987    #[test]
988    fn test_cookie_parse() {
989        let resp: Response = CookieParseError::EmptyName.error_response();
990        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
991    }
992
993    #[test]
994    fn test_as_response() {
995        let orig = io::Error::new(io::ErrorKind::Other, "other");
996        let e: Error = ParseError::Io(orig).into();
997        assert_eq!(format!("{}", e.as_response_error()), "IO error: other");
998    }
999
1000    #[test]
1001    fn test_error_cause() {
1002        let orig = io::Error::new(io::ErrorKind::Other, "other");
1003        let desc = orig.to_string();
1004        let e = Error::from(orig);
1005        assert_eq!(format!("{}", e.as_response_error()), desc);
1006    }
1007
1008    #[test]
1009    fn test_error_display() {
1010        let orig = io::Error::new(io::ErrorKind::Other, "other");
1011        let desc = orig.to_string();
1012        let e = Error::from(orig);
1013        assert_eq!(format!("{}", e), desc);
1014    }
1015
1016    #[test]
1017    fn test_error_http_response() {
1018        let orig = io::Error::new(io::ErrorKind::Other, "other");
1019        let e = Error::from(orig);
1020        let resp: Response = e.into();
1021        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1022    }
1023
1024    #[test]
1025    fn test_payload_error() {
1026        let err: PayloadError =
1027            io::Error::new(io::ErrorKind::Other, "ParseError").into();
1028        assert!(format!("{}", err).contains("ParseError"));
1029
1030        let err = PayloadError::Incomplete(None);
1031        assert_eq!(
1032            format!("{}", err),
1033            "A payload reached EOF, but is not complete. With error: None"
1034        );
1035    }
1036
1037    macro_rules! from {
1038        ($from:expr => $error:pat) => {
1039            match ParseError::from($from) {
1040                e @ $error => {
1041                    assert!(format!("{}", e).len() >= 5);
1042                }
1043                e => unreachable!("{:?}", e),
1044            }
1045        };
1046    }
1047
1048    macro_rules! from_and_cause {
1049        ($from:expr => $error:pat) => {
1050            match ParseError::from($from) {
1051                e @ $error => {
1052                    let desc = format!("{}", e);
1053                    assert_eq!(desc, format!("IO error: {}", $from));
1054                }
1055                _ => unreachable!("{:?}", $from),
1056            }
1057        };
1058    }
1059
1060    #[test]
1061    fn test_from() {
1062        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..));
1063        from!(httparse::Error::HeaderName => ParseError::Header);
1064        from!(httparse::Error::HeaderName => ParseError::Header);
1065        from!(httparse::Error::HeaderValue => ParseError::Header);
1066        from!(httparse::Error::NewLine => ParseError::Header);
1067        from!(httparse::Error::Status => ParseError::Status);
1068        from!(httparse::Error::Token => ParseError::Header);
1069        from!(httparse::Error::TooManyHeaders => ParseError::TooLarge);
1070        from!(httparse::Error::Version => ParseError::Version);
1071    }
1072
1073    #[test]
1074    fn test_internal_error() {
1075        let err =
1076            InternalError::from_response(ParseError::Method, Response::Ok().into());
1077        let resp: Response = err.error_response();
1078        assert_eq!(resp.status(), StatusCode::OK);
1079    }
1080
1081    #[test]
1082    fn test_error_casting() {
1083        let err = PayloadError::Overflow;
1084        let resp_err: &dyn ResponseError = &err;
1085        let err = resp_err.downcast_ref::<PayloadError>().unwrap();
1086        assert_eq!(err.to_string(), "A payload reached size limit.");
1087        let not_err = resp_err.downcast_ref::<ContentTypeError>();
1088        assert!(not_err.is_none());
1089    }
1090
1091    #[test]
1092    fn test_error_helpers() {
1093        let r: Response = ErrorBadRequest("err").into();
1094        assert_eq!(r.status(), StatusCode::BAD_REQUEST);
1095
1096        let r: Response = ErrorUnauthorized("err").into();
1097        assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
1098
1099        let r: Response = ErrorPaymentRequired("err").into();
1100        assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
1101
1102        let r: Response = ErrorForbidden("err").into();
1103        assert_eq!(r.status(), StatusCode::FORBIDDEN);
1104
1105        let r: Response = ErrorNotFound("err").into();
1106        assert_eq!(r.status(), StatusCode::NOT_FOUND);
1107
1108        let r: Response = ErrorMethodNotAllowed("err").into();
1109        assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
1110
1111        let r: Response = ErrorNotAcceptable("err").into();
1112        assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
1113
1114        let r: Response = ErrorProxyAuthenticationRequired("err").into();
1115        assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
1116
1117        let r: Response = ErrorRequestTimeout("err").into();
1118        assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
1119
1120        let r: Response = ErrorConflict("err").into();
1121        assert_eq!(r.status(), StatusCode::CONFLICT);
1122
1123        let r: Response = ErrorGone("err").into();
1124        assert_eq!(r.status(), StatusCode::GONE);
1125
1126        let r: Response = ErrorLengthRequired("err").into();
1127        assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
1128
1129        let r: Response = ErrorPreconditionFailed("err").into();
1130        assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
1131
1132        let r: Response = ErrorPayloadTooLarge("err").into();
1133        assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
1134
1135        let r: Response = ErrorUriTooLong("err").into();
1136        assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
1137
1138        let r: Response = ErrorUnsupportedMediaType("err").into();
1139        assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
1140
1141        let r: Response = ErrorRangeNotSatisfiable("err").into();
1142        assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
1143
1144        let r: Response = ErrorExpectationFailed("err").into();
1145        assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
1146
1147        let r: Response = ErrorImATeapot("err").into();
1148        assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
1149
1150        let r: Response = ErrorMisdirectedRequest("err").into();
1151        assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
1152
1153        let r: Response = ErrorUnprocessableEntity("err").into();
1154        assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
1155
1156        let r: Response = ErrorLocked("err").into();
1157        assert_eq!(r.status(), StatusCode::LOCKED);
1158
1159        let r: Response = ErrorFailedDependency("err").into();
1160        assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
1161
1162        let r: Response = ErrorUpgradeRequired("err").into();
1163        assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
1164
1165        let r: Response = ErrorPreconditionRequired("err").into();
1166        assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
1167
1168        let r: Response = ErrorTooManyRequests("err").into();
1169        assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
1170
1171        let r: Response = ErrorRequestHeaderFieldsTooLarge("err").into();
1172        assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
1173
1174        let r: Response = ErrorUnavailableForLegalReasons("err").into();
1175        assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
1176
1177        let r: Response = ErrorInternalServerError("err").into();
1178        assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
1179
1180        let r: Response = ErrorNotImplemented("err").into();
1181        assert_eq!(r.status(), StatusCode::NOT_IMPLEMENTED);
1182
1183        let r: Response = ErrorBadGateway("err").into();
1184        assert_eq!(r.status(), StatusCode::BAD_GATEWAY);
1185
1186        let r: Response = ErrorServiceUnavailable("err").into();
1187        assert_eq!(r.status(), StatusCode::SERVICE_UNAVAILABLE);
1188
1189        let r: Response = ErrorGatewayTimeout("err").into();
1190        assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
1191
1192        let r: Response = ErrorHttpVersionNotSupported("err").into();
1193        assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
1194
1195        let r: Response = ErrorVariantAlsoNegotiates("err").into();
1196        assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
1197
1198        let r: Response = ErrorInsufficientStorage("err").into();
1199        assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
1200
1201        let r: Response = ErrorLoopDetected("err").into();
1202        assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
1203
1204        let r: Response = ErrorNotExtended("err").into();
1205        assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
1206
1207        let r: Response = ErrorNetworkAuthenticationRequired("err").into();
1208        assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
1209    }
1210}