1use std::io;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("HTTP protocol error: {0}")]
13 HttpProtocol(String),
14
15 #[error("HTTP {status}: {message}")]
17 HttpStatus { status: u16, message: String },
18
19 #[error("Redirect limit exceeded ({count} redirects)")]
21 RedirectLimit { count: u32 },
22
23 #[error("Invalid redirect URL: {0}")]
25 InvalidRedirectUrl(String),
26
27 #[error("Cookie parse error: {0}")]
29 CookieParse(String),
30
31 #[error("Decompression error: {0}")]
33 Decompression(String),
34
35 #[error("URL parse error: {0}")]
37 UrlParse(#[from] url::ParseError),
38
39 #[error("JSON error: {0}")]
41 Json(#[from] serde_json::Error),
42
43 #[error("URL encoding error: {0}")]
45 UrlEncode(#[from] serde_urlencoded::ser::Error),
46
47 #[error("IO error: {0}")]
49 Io(#[from] io::Error),
50
51 #[error("Missing required: {0}")]
53 Missing(String),
54
55 #[error("Operation timed out: {0}")]
57 Timeout(String),
58
59 #[error("Connect timeout after {0:?}")]
61 ConnectTimeout(std::time::Duration),
62
63 #[error("TTFB timeout after {0:?} - server did not respond with headers")]
65 TtfbTimeout(std::time::Duration),
66
67 #[error("Read idle timeout after {0:?} - stream may be hung")]
69 ReadIdleTimeout(std::time::Duration),
70
71 #[error("Write idle timeout after {0:?}")]
73 WriteIdleTimeout(std::time::Duration),
74
75 #[error("Total request deadline exceeded after {0:?}")]
77 TotalTimeout(std::time::Duration),
78
79 #[error("Pool acquire timeout after {0:?} - no connections available")]
81 PoolAcquireTimeout(std::time::Duration),
82
83 #[error("Connection error: {0}")]
85 Connection(String),
86
87 #[error("TLS error: {0}")]
89 Tls(String),
90
91 #[error("QUIC error: {0}")]
93 Quic(String),
94
95 #[error("SETTINGS_TIMEOUT (0x04): No SETTINGS frame received within {0:?}")]
97 SettingsTimeout(std::time::Duration),
98}
99
100impl Error {
101 pub fn http_status(status: u16, message: impl Into<String>) -> Self {
103 Self::HttpStatus {
104 status,
105 message: message.into(),
106 }
107 }
108
109 pub fn missing(field: impl Into<String>) -> Self {
111 Self::Missing(field.into())
112 }
113
114 pub fn io(message: impl Into<String>) -> Self {
116 Self::Io(io::Error::other(message.into()))
117 }
118
119 pub fn http_protocol(message: impl Into<String>) -> Self {
121 Self::HttpProtocol(message.into())
122 }
123
124 pub fn connection(message: impl Into<String>) -> Self {
126 Self::Connection(message.into())
127 }
128
129 pub fn timeout(message: impl Into<String>) -> Self {
131 Self::Timeout(message.into())
132 }
133
134 pub fn tls(message: impl Into<String>) -> Self {
136 Self::Tls(message.into())
137 }
138
139 pub fn quic(message: impl Into<String>) -> Self {
141 Self::Quic(message.into())
142 }
143}