1use super::response::{Metrics, ResponseInfo, ResponseParts};
2use anyhow::Error as AnyError;
3use http::uri::{Scheme, Uri};
4use std::{
5 error::Error as StdError,
6 fmt::{self, Debug, Display},
7 net::IpAddr,
8 num::NonZeroU16,
9};
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum ErrorKind {
15 ProtocolError,
17
18 InvalidRequestResponse,
20
21 InvalidUrl,
23
24 InvalidHeader,
26
27 ConnectError,
29
30 ProxyError,
32
33 DnsServerError,
35
36 UnknownHostError,
38
39 SendError,
41
42 ReceiveError,
44
45 LocalIoError,
47
48 TimeoutError,
50
51 ClientCertError,
53
54 ServerCertError,
56
57 SslError,
59
60 TooManyRedirect,
62
63 UnknownError,
65
66 CallbackError,
68}
69
70#[derive(Debug)]
72pub struct Error {
73 kind: ErrorKind,
74 error: AnyError,
75 response_info: ResponseInfo,
76}
77
78impl Error {
79 #[inline]
81 pub fn builder(kind: ErrorKind, err: impl Into<AnyError>) -> ErrorBuilder {
82 ErrorBuilder::new(kind, err)
83 }
84
85 #[inline]
87 pub fn builder_with_msg(kind: ErrorKind, err: impl Display + Debug + Send + Sync + 'static) -> ErrorBuilder {
88 ErrorBuilder::new_with_msg(kind, err)
89 }
90
91 #[inline]
93 pub fn kind(&self) -> ErrorKind {
94 self.kind
95 }
96
97 #[inline]
99 pub fn into_inner(self) -> AnyError {
100 self.error
101 }
102
103 #[inline]
105 pub fn server_ip(&self) -> Option<IpAddr> {
106 self.response_info.server_ip()
107 }
108
109 #[inline]
111 pub fn server_port(&self) -> Option<NonZeroU16> {
112 self.response_info.server_port()
113 }
114
115 #[inline]
117 pub fn metrics(&self) -> Option<&Metrics> {
118 self.response_info.metrics()
119 }
120
121 #[inline]
123 pub fn server_ip_mut(&mut self) -> &mut Option<IpAddr> {
124 self.response_info.server_ip_mut()
125 }
126
127 #[inline]
129 pub fn server_port_mut(&mut self) -> &mut Option<NonZeroU16> {
130 self.response_info.server_port_mut()
131 }
132
133 #[inline]
135 pub fn metrics_mut(&mut self) -> &mut Option<Metrics> {
136 self.response_info.metrics_mut()
137 }
138}
139
140impl Display for Error {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 Display::fmt(&self.error, f)
143 }
144}
145
146impl StdError for Error {
147 #[inline]
148 fn source(&self) -> Option<&(dyn StdError + 'static)> {
149 Some(self.error.as_ref())
150 }
151}
152
153#[derive(Debug)]
155pub struct ErrorBuilder {
156 inner: Error,
157}
158
159impl ErrorBuilder {
160 #[inline]
162 fn new(kind: ErrorKind, err: impl Into<AnyError>) -> Self {
163 Self {
164 inner: Error {
165 kind,
166 error: err.into(),
167 response_info: Default::default(),
168 },
169 }
170 }
171
172 #[inline]
174 fn new_with_msg(kind: ErrorKind, msg: impl Display + Debug + Send + Sync + 'static) -> Self {
175 Self {
176 inner: Error {
177 kind,
178 error: AnyError::msg(msg),
179 response_info: Default::default(),
180 },
181 }
182 }
183
184 #[inline]
186 pub fn build(self) -> Error {
187 self.inner
188 }
189
190 #[must_use]
192 pub fn uri(mut self, uri: &Uri) -> Self {
193 if let Some(host) = uri.host() {
194 if let Ok(ip_addr) = host.parse::<IpAddr>() {
195 *self.inner.server_ip_mut() = Some(ip_addr);
196 }
197 }
198 if let Some(port) = uri.port_u16() {
199 *self.inner.server_port_mut() = NonZeroU16::new(port);
200 } else if let Some(scheme) = uri.scheme() {
201 if scheme == &Scheme::HTTP {
202 *self.inner.server_port_mut() = NonZeroU16::new(80);
203 } else if scheme == &Scheme::HTTPS {
204 *self.inner.server_port_mut() = NonZeroU16::new(443);
205 }
206 }
207 self
208 }
209
210 #[inline]
212 #[must_use]
213 pub fn server_ip(mut self, server_ip: IpAddr) -> Self {
214 *self.inner.server_ip_mut() = Some(server_ip);
215 self
216 }
217
218 #[inline]
220 #[must_use]
221 pub fn server_port(mut self, server_port: NonZeroU16) -> Self {
222 *self.inner.server_port_mut() = Some(server_port);
223 self
224 }
225
226 #[inline]
228 #[must_use]
229 pub fn metrics(mut self, metrics: Metrics) -> Self {
230 *self.inner.metrics_mut() = Some(metrics);
231 self
232 }
233}
234
235#[derive(Debug)]
237pub struct MapError<E> {
238 error: E,
239 parts: ResponseParts,
240}
241
242impl<E> MapError<E> {
243 pub(super) fn new(error: E, parts: ResponseParts) -> Self {
244 Self { error, parts }
245 }
246
247 #[inline]
249 pub fn into_inner(self) -> E {
250 self.error
251 }
252}
253
254impl<E: Into<AnyError>> MapError<E> {
255 pub fn into_response_error(self, kind: ErrorKind) -> Error {
257 Error {
258 kind,
259 error: self.error.into(),
260 response_info: self.parts.into_response_info(),
261 }
262 }
263}