1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::io;
use std::convert::From;

use futures::sync::mpsc::SendError;
use httparse::Error as HttpError;
use httparse::InvalidChunkSize;


quick_error! {
    #[derive(Debug)]
    /// HTTP client error
    pub enum Error wraps pub ErrorEnum {
        /// I/O (basically networking) error occured during request
        Io(err: io::Error) {
            description("IO error")
            display("IO error: {}", err)
            from()
        }
        /// Bad response headers received
        Header(err: HttpError) {
            description("bad headers")
            display("bad headers: {}", err)
            from()
        }
        /// Bad chunk size received
        ChunkSize(err: InvalidChunkSize) {
            description("invalid chunk size")
            display("invalid chunk size: {}", err)
            from()
        }
        /// Bad `Content-Length` header
        BadContentLength {
            description("bad content length")
        }
        /// Duplicate `Content-Length` header
        DuplicateContentLength {
            description("duplicate content length")
        }
        /// Connection reset by peer when reading response headers
        ResetOnResponseHeaders {
            description("connection closed prematurely while reading headers")
        }
        /// Connection reset by peer when response body
        ResetOnResponseBody {
            description("connection closed prematurely while reading body")
        }
        /// Response headers are received while we had no request sent yet
        PrematureResponseHeaders {
            description("response headers received \
                         before request has been written")
        }
        /// This means connection is busy (over the limit or not yet
        /// established when trying to send request
        Busy {
            description("request can't be sent because connection is busy")
        }
        /// The channel for receiving response is canceled. This probably means
        /// that connection to server was closed before being able to fulfil
        /// the request. But it's unlikely that this error is related to this
        /// request itself.
        Canceled {
            description("request canceled")
        }
        /// Connection closed normally
        ///
        /// This error should be catched by connection poolm and not shown
        /// to the end users
        Closed {
            description("connection closed normally")
        }
        /// Invalid URL specified
        InvalidUrl {
            description("requesting an invalid url")
        }
        /// Error sending a request to a connection pool
        PoolError {
            description("error sending a request to a connection pool")
        }
        /// Request body is too big (happens only in buffered mode)
        ResponseBodyTooLong {
            description("response body too long")
        }
        /// Connection header is invalid
        ConnectionInvalid {
            description("invalid connection header in response")
        }
        /// Unsupported status returned by server
        ///
        /// You have to write your own Codec to handle unsupported status codes
        InvalidStatus {
            description("unsupported status")
        }
        /// Request timed out
        RequestTimeout {
            description("request timed out")
        }
        /// Connection timed out on keep alive
        KeepAliveTimeout {
            description("connection timed out beeing on keep-alive")
        }
        Custom(err: Box<::std::error::Error + Send + Sync>) {
            description("custom error")
            display("custom error: {}", err)
            cause(&**err)
        }
    }
}

impl<T> From<SendError<T>> for ErrorEnum {
    fn from(_: SendError<T>) -> ErrorEnum {
        ErrorEnum::PoolError
    }
}

impl Error {
    /// Create an error instance wrapping custom error
    pub fn custom<E: Into<Box<::std::error::Error + Send + Sync>>>(err: E)
        -> Error
    {
        Error(ErrorEnum::Custom(err.into()))
    }
}

#[test]
fn send_sync() {
    fn send_sync<T: Send+Sync>(_: T) {}
    send_sync(Error::from(ErrorEnum::Canceled));
}