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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use std::io;
use std::fmt;
use std::convert::From;
use futures::sync::mpsc::SendError;
use httparse::Error as HttpError;
use httparse::InvalidChunkSize;
/// HTTP client error
pub struct Error(ErrorEnum);
quick_error! {
#[derive(Debug)]
/// Client request error
pub enum 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")
cause(&**err)
}
}
}
impl<T> From<SendError<T>> for ErrorEnum {
fn from(_: SendError<T>) -> ErrorEnum {
ErrorEnum::PoolError
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl From<ErrorEnum> for Error {
fn from(err: ErrorEnum) -> Self {
Error(err)
}
}
impl ::std::error::Error for Error {
fn description(&self) -> &str {
self.0.description()
}
fn cause(&self) -> Option<&::std::error::Error> {
self.0.cause()
}
}
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));
}