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}