minreq/error.rs
1use std::{error, fmt, io, str};
2
3/// Represents an error while sending, receiving, or parsing an HTTP response.
4#[derive(Debug)]
5// TODO: Make non-exhaustive for 3.0?
6pub enum Error {
7 /// The response body contains invalid UTF-8, so the `as_str()`
8 /// conversion failed.
9 InvalidUtf8InBody(str::Utf8Error),
10 /// Ran into a rustls error while creating the connection.
11 RustlsCreateConnection(rustls::Error),
12 /// Ran into an IO problem while loading the response.
13 IoError(io::Error),
14 /// Couldn't parse the incoming chunk's length while receiving a
15 /// response with the header `Transfer-Encoding: chunked`.
16 MalformedChunkLength,
17 /// The chunk did not end after reading the previously read amount
18 /// of bytes.
19 MalformedChunkEnd,
20 /// Couldn't parse the `Content-Length` header's value as an
21 /// `usize`.
22 MalformedContentLength,
23 /// The response contains headers whose total size surpasses
24 /// [Request::with_max_headers_size](crate::request::Request::with_max_headers_size).
25 HeadersOverflow,
26 /// The response's status line length surpasses
27 /// [Request::with_max_status_line_size](crate::request::Request::with_max_status_line_length).
28 StatusLineOverflow,
29 /// [ToSocketAddrs](std::net::ToSocketAddrs) did not resolve to an
30 /// address.
31 AddressNotFound,
32 /// The response was a redirection, but the `Location` header is
33 /// missing.
34 RedirectLocationMissing,
35 /// The response redirections caused an infinite redirection loop.
36 InfiniteRedirectionLoop,
37 /// Followed
38 /// [`max_redirections`](struct.Request.html#method.with_max_redirections)
39 /// redirections, won't follow any more.
40 TooManyRedirections,
41 /// The response contained invalid UTF-8 where it should be valid
42 /// (eg. headers), so the response cannot interpreted correctly.
43 InvalidUtf8InResponse,
44 /// The provided url contained a domain that has non-ASCII
45 /// characters, and could not be converted into punycode. It is
46 /// probably not an actual domain.
47 PunycodeConversionFailed,
48 /// Tried to send a secure request (ie. the url started with
49 /// `https://`), but the crate's `https` feature was not enabled,
50 /// and as such, a connection cannot be made.
51 HttpsFeatureNotEnabled,
52 /// The provided url contained a domain that has non-ASCII
53 /// characters, but it could not be converted into punycode
54 /// because the `punycode` feature was not enabled.
55 PunycodeFeatureNotEnabled,
56 /// The provided proxy information was not properly formatted. See
57 /// [Proxy::new](crate::Proxy::new) for the valid format.
58 BadProxy,
59 /// The provided credentials were rejected by the proxy server.
60 BadProxyCreds,
61 /// The provided proxy credentials were malformed.
62 ProxyConnect,
63 /// The provided credentials were rejected by the proxy server.
64 InvalidProxyCreds,
65 // TODO: Uncomment these two for 3.0
66 // /// The URL does not start with http:// or https://.
67 // InvalidProtocol,
68 // /// The URL ended up redirecting to an URL that does not start
69 // /// with http:// or https://.
70 // InvalidProtocolInRedirect,
71 /// This is a special error case, one that should never be
72 /// returned! Think of this as a cleaner alternative to calling
73 /// `unreachable!()` inside the library. If you come across this,
74 /// please open an issue, and include the string inside this
75 /// error, as it can be used to locate the problem.
76 Other(&'static str),
77}
78
79impl fmt::Display for Error {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 use Error::*;
82 match self {
83 IoError(err) => write!(f, "{}", err),
84 InvalidUtf8InBody(err) => write!(f, "{}", err),
85 RustlsCreateConnection(err) => write!(f, "error creating rustls connection: {}", err),
86 MalformedChunkLength => write!(f, "non-usize chunk length with transfer-encoding: chunked"),
87 MalformedChunkEnd => write!(f, "chunk did not end after reading the expected amount of bytes"),
88 MalformedContentLength => write!(f, "non-usize content length"),
89 HeadersOverflow => write!(f, "the headers' total size surpassed max_headers_size"),
90 StatusLineOverflow => write!(f, "the status line length surpassed max_status_line_length"),
91 AddressNotFound => write!(f, "could not resolve host to a socket address"),
92 RedirectLocationMissing => write!(f, "redirection location header missing"),
93 InfiniteRedirectionLoop => write!(f, "infinite redirection loop detected"),
94 TooManyRedirections => write!(f, "too many redirections (over the max)"),
95 InvalidUtf8InResponse => write!(f, "response contained invalid utf-8 where valid utf-8 was expected"),
96 HttpsFeatureNotEnabled => write!(f, "request url contains https:// but the https feature is not enabled"),
97 PunycodeFeatureNotEnabled => write!(f, "non-ascii urls needs to be converted into punycode, and the feature is missing"),
98 PunycodeConversionFailed => write!(f, "non-ascii url conversion to punycode failed"),
99 BadProxy => write!(f, "the provided proxy information is malformed"),
100 BadProxyCreds => write!(f, "the provided proxy credentials are malformed"),
101 ProxyConnect => write!(f, "could not connect to the proxy server"),
102 InvalidProxyCreds => write!(f, "the provided proxy credentials are invalid"),
103 // TODO: Uncomment these two for 3.0
104 // InvalidProtocol => write!(f, "the url does not start with http:// or https://"),
105 // InvalidProtocolInRedirect => write!(f, "got redirected to an absolute url which does not start with http:// or https://"),
106 Other(msg) => write!(f, "error in minreq: please open an issue in the minreq repo, include the following: '{}'", msg),
107 }
108 }
109}
110
111impl error::Error for Error {
112 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
113 use Error::*;
114 match self {
115 IoError(err) => Some(err),
116 InvalidUtf8InBody(err) => Some(err),
117 RustlsCreateConnection(err) => Some(err),
118 _ => None,
119 }
120 }
121}
122
123impl From<io::Error> for Error {
124 fn from(other: io::Error) -> Error {
125 Error::IoError(other)
126 }
127}