Skip to main content

wasmtime_wasi_http/
error.rs

1use std::fmt;
2use std::io;
3
4/// Error type for `wasi:http` embedder interactions.
5///
6/// This error type is a superset of the wasip2/wasip3 error types for example
7/// and is the error that the embedder interacts with for all operations.
8#[derive(Debug)]
9#[non_exhaustive]
10#[expect(missing_docs, reason = "too cluttered")]
11pub enum Error {
12    Hyper(hyper::Error),
13    Connect(io::Error),
14    Tls(io::Error),
15    #[cfg(feature = "default-send-request")]
16    InvalidDnsNameError(rustls::pki_types::InvalidDnsNameError),
17    HttpRequestBodySize(Option<u64>),
18
19    DnsTimeout,
20    DnsError {
21        rcode: Option<String>,
22        info_code: Option<u16>,
23    },
24    DestinationNotFound,
25    DestinationUnavailable,
26    DestinationIpProhibited,
27    DestinationIpUnroutable,
28    ConnectionRefused,
29    ConnectionTerminated,
30    ConnectionTimeout,
31    ConnectionReadTimeout,
32    ConnectionWriteTimeout,
33    ConnectionLimitReached,
34    TlsProtocolError,
35    TlsCertificateError,
36    TlsAlertReceived {
37        alert_id: Option<u8>,
38        alert_message: Option<String>,
39    },
40    HttpRequestDenied,
41    HttpRequestLengthRequired,
42    HttpRequestMethodInvalid,
43    HttpRequestUriInvalid,
44    HttpRequestUriTooLong,
45    HttpRequestHeaderSectionSize(Option<u32>),
46    HttpRequestHeaderSize {
47        field_name: Option<String>,
48        field_size: Option<u32>,
49    },
50    HttpRequestTrailerSectionSize(Option<u32>),
51    HttpRequestTrailerSize {
52        field_name: Option<String>,
53        field_size: Option<u32>,
54    },
55    HttpResponseIncomplete,
56    HttpResponseHeaderSectionSize(Option<u32>),
57    HttpResponseHeaderSize {
58        field_name: Option<String>,
59        field_size: Option<u32>,
60    },
61    HttpResponseBodySize(Option<u64>),
62    HttpResponseTrailerSectionSize(Option<u32>),
63    HttpResponseTrailerSize {
64        field_name: Option<String>,
65        field_size: Option<u32>,
66    },
67    HttpResponseTransferCoding(Option<String>),
68    HttpResponseContentCoding(Option<String>),
69    HttpResponseTimeout,
70    HttpUpgradeFailed,
71    HttpProtocolError,
72    LoopDetected,
73    ConfigurationError,
74    InternalError(Option<String>),
75}
76
77/// Convenience type for a result with [`Error`]
78pub type Result<T, E = Error> = std::result::Result<T, E>;
79
80impl From<hyper::Error> for Error {
81    fn from(err: hyper::Error) -> Self {
82        Self::Hyper(err)
83    }
84}
85
86impl From<std::convert::Infallible> for Error {
87    fn from(e: std::convert::Infallible) -> Self {
88        match e {}
89    }
90}
91
92#[cfg(feature = "default-send-request")]
93impl From<rustls::pki_types::InvalidDnsNameError> for Error {
94    fn from(err: rustls::pki_types::InvalidDnsNameError) -> Self {
95        Self::InvalidDnsNameError(err)
96    }
97}
98
99impl fmt::Display for Error {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        match self {
102            Self::Hyper(err) => write!(f, "hyper error: {err}"),
103            Self::Connect(err) => write!(f, "connection error: {err}"),
104            Self::Tls(err) => write!(f, "TLS error: {err}"),
105            #[cfg(feature = "default-send-request")]
106            Self::InvalidDnsNameError(err) => write!(f, "invalid DNS name: {err}"),
107            Self::HttpRequestBodySize(None) => {
108                write!(f, "HTTP request body size exceeds limit")
109            }
110            Self::HttpRequestBodySize(Some(size)) => {
111                write!(f, "HTTP request body size exceeds limit: {size} bytes")
112            }
113            Self::DnsTimeout => write!(f, "DNS lookup timed out"),
114            Self::DnsError { rcode, info_code } => {
115                write!(f, "DNS error")?;
116                if let Some(rcode) = rcode {
117                    write!(f, ": rcode {rcode}")?;
118                }
119                if let Some(info_code) = info_code {
120                    write!(f, " (info code {info_code})")?;
121                }
122                Ok(())
123            }
124            Self::DestinationNotFound => write!(f, "destination not found"),
125            Self::DestinationUnavailable => write!(f, "destination unavailable"),
126            Self::DestinationIpProhibited => write!(f, "destination IP address is prohibited"),
127            Self::DestinationIpUnroutable => write!(f, "destination IP address is unroutable"),
128            Self::ConnectionRefused => write!(f, "connection refused"),
129            Self::ConnectionTerminated => write!(f, "connection terminated"),
130            Self::ConnectionTimeout => write!(f, "connection timeout"),
131            Self::ConnectionReadTimeout => write!(f, "connection read timeout"),
132            Self::ConnectionWriteTimeout => write!(f, "connection write timeout"),
133            Self::ConnectionLimitReached => write!(f, "connection limit reached"),
134            Self::TlsProtocolError => write!(f, "TLS protocol error"),
135            Self::TlsCertificateError => write!(f, "TLS certificate error"),
136            Self::TlsAlertReceived {
137                alert_id,
138                alert_message,
139            } => {
140                write!(f, "TLS alert received")?;
141                if let Some(id) = alert_id {
142                    write!(f, ": alert id {id}")?;
143                }
144                if let Some(msg) = alert_message {
145                    write!(f, ": {msg}")?;
146                }
147                Ok(())
148            }
149            Self::HttpRequestDenied => write!(f, "HTTP request denied"),
150            Self::HttpRequestLengthRequired => write!(f, "HTTP request length required"),
151            Self::HttpRequestMethodInvalid => write!(f, "invalid HTTP request method"),
152            Self::HttpRequestUriInvalid => write!(f, "invalid HTTP request URI"),
153            Self::HttpRequestUriTooLong => write!(f, "HTTP request URI too long"),
154            Self::HttpRequestHeaderSectionSize(size) => {
155                write!(f, "HTTP request header section size exceeds limit")?;
156                if let Some(size) = size {
157                    write!(f, ": {size} bytes")?;
158                }
159                Ok(())
160            }
161            Self::HttpRequestHeaderSize {
162                field_name,
163                field_size,
164            } => {
165                write!(f, "HTTP request header size exceeds limit")?;
166                if let Some(name) = field_name {
167                    write!(f, ": field {name:?}")?;
168                }
169                if let Some(size) = field_size {
170                    write!(f, " ({size} bytes)")?;
171                }
172                Ok(())
173            }
174            Self::HttpRequestTrailerSectionSize(size) => {
175                write!(f, "HTTP request trailer section size exceeds limit")?;
176                if let Some(size) = size {
177                    write!(f, ": {size} bytes")?;
178                }
179                Ok(())
180            }
181            Self::HttpRequestTrailerSize {
182                field_name,
183                field_size,
184            } => {
185                write!(f, "HTTP request trailer size exceeds limit")?;
186                if let Some(name) = field_name {
187                    write!(f, ": field {name:?}")?;
188                }
189                if let Some(size) = field_size {
190                    write!(f, " ({size} bytes)")?;
191                }
192                Ok(())
193            }
194            Self::HttpResponseIncomplete => write!(f, "incomplete HTTP response"),
195            Self::HttpResponseHeaderSectionSize(size) => {
196                write!(f, "HTTP response header section size exceeds limit")?;
197                if let Some(size) = size {
198                    write!(f, ": {size} bytes")?;
199                }
200                Ok(())
201            }
202            Self::HttpResponseHeaderSize {
203                field_name,
204                field_size,
205            } => {
206                write!(f, "HTTP response header size exceeds limit")?;
207                if let Some(name) = field_name {
208                    write!(f, ": field {name:?}")?;
209                }
210                if let Some(size) = field_size {
211                    write!(f, " ({size} bytes)")?;
212                }
213                Ok(())
214            }
215            Self::HttpResponseBodySize(size) => {
216                write!(f, "HTTP response body size exceeds limit")?;
217                if let Some(size) = size {
218                    write!(f, ": {size} bytes")?;
219                }
220                Ok(())
221            }
222            Self::HttpResponseTrailerSectionSize(size) => {
223                write!(f, "HTTP response trailer section size exceeds limit")?;
224                if let Some(size) = size {
225                    write!(f, ": {size} bytes")?;
226                }
227                Ok(())
228            }
229            Self::HttpResponseTrailerSize {
230                field_name,
231                field_size,
232            } => {
233                write!(f, "HTTP response trailer size exceeds limit")?;
234                if let Some(name) = field_name {
235                    write!(f, ": field {name:?}")?;
236                }
237                if let Some(size) = field_size {
238                    write!(f, " ({size} bytes)")?;
239                }
240                Ok(())
241            }
242            Self::HttpResponseTransferCoding(coding) => {
243                write!(f, "unsupported HTTP response transfer coding")?;
244                if let Some(coding) = coding {
245                    write!(f, ": {coding:?}")?;
246                }
247                Ok(())
248            }
249            Self::HttpResponseContentCoding(coding) => {
250                write!(f, "unsupported HTTP response content coding")?;
251                if let Some(coding) = coding {
252                    write!(f, ": {coding:?}")?;
253                }
254                Ok(())
255            }
256            Self::HttpResponseTimeout => write!(f, "HTTP response timeout"),
257            Self::HttpUpgradeFailed => write!(f, "HTTP upgrade failed"),
258            Self::HttpProtocolError => write!(f, "HTTP protocol error"),
259            Self::LoopDetected => write!(f, "request loop detected"),
260            Self::ConfigurationError => write!(f, "configuration error"),
261            Self::InternalError(None) => write!(f, "internal error"),
262            Self::InternalError(Some(msg)) => write!(f, "internal error: {msg}"),
263        }
264    }
265}
266
267impl std::error::Error for Error {}