Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-http/src/error.rs
1692 views
1
use crate::bindings::http::types::ErrorCode;
2
use std::error::Error;
3
use std::fmt;
4
use wasmtime::component::ResourceTableError;
5
6
/// A [`Result`] type where the error type defaults to [`HttpError`].
7
pub type HttpResult<T, E = HttpError> = Result<T, E>;
8
9
/// A `wasi:http`-specific error type used to represent either a trap or an
10
/// [`ErrorCode`].
11
///
12
/// Modeled after [`TrappableError`](wasmtime_wasi::TrappableError).
13
#[repr(transparent)]
14
pub struct HttpError {
15
err: anyhow::Error,
16
}
17
18
impl HttpError {
19
/// Create a new `HttpError` that represents a trap.
20
pub fn trap(err: impl Into<anyhow::Error>) -> HttpError {
21
HttpError { err: err.into() }
22
}
23
24
/// Downcast this error to an [`ErrorCode`].
25
pub fn downcast(self) -> anyhow::Result<ErrorCode> {
26
self.err.downcast()
27
}
28
29
/// Downcast this error to a reference to an [`ErrorCode`]
30
pub fn downcast_ref(&self) -> Option<&ErrorCode> {
31
self.err.downcast_ref()
32
}
33
}
34
35
impl From<ErrorCode> for HttpError {
36
fn from(error: ErrorCode) -> Self {
37
Self { err: error.into() }
38
}
39
}
40
41
impl From<ResourceTableError> for HttpError {
42
fn from(error: ResourceTableError) -> Self {
43
HttpError::trap(error)
44
}
45
}
46
47
impl fmt::Debug for HttpError {
48
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49
self.err.fmt(f)
50
}
51
}
52
53
impl fmt::Display for HttpError {
54
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55
self.err.fmt(f)
56
}
57
}
58
59
impl Error for HttpError {}
60
61
#[cfg(feature = "default-send-request")]
62
pub(crate) fn dns_error(rcode: String, info_code: u16) -> ErrorCode {
63
ErrorCode::DnsError(crate::bindings::http::types::DnsErrorPayload {
64
rcode: Some(rcode),
65
info_code: Some(info_code),
66
})
67
}
68
69
pub(crate) fn internal_error(msg: String) -> ErrorCode {
70
ErrorCode::InternalError(Some(msg))
71
}
72
73
/// Translate a [`http::Error`] to a wasi-http `ErrorCode` in the context of a request.
74
pub fn http_request_error(err: http::Error) -> ErrorCode {
75
if err.is::<http::uri::InvalidUri>() {
76
return ErrorCode::HttpRequestUriInvalid;
77
}
78
79
tracing::warn!("http request error: {err:?}");
80
81
ErrorCode::HttpProtocolError
82
}
83
84
/// Translate a [`hyper::Error`] to a wasi-http `ErrorCode` in the context of a request.
85
pub fn hyper_request_error(err: hyper::Error) -> ErrorCode {
86
// If there's a source, we might be able to extract a wasi-http error from it.
87
if let Some(cause) = err.source() {
88
if let Some(err) = cause.downcast_ref::<ErrorCode>() {
89
return err.clone();
90
}
91
}
92
93
tracing::warn!("hyper request error: {err:?}");
94
95
ErrorCode::HttpProtocolError
96
}
97
98
/// Translate a [`hyper::Error`] to a wasi-http `ErrorCode` in the context of a response.
99
pub fn hyper_response_error(err: hyper::Error) -> ErrorCode {
100
if err.is_timeout() {
101
return ErrorCode::HttpResponseTimeout;
102
}
103
104
// If there's a source, we might be able to extract a wasi-http error from it.
105
if let Some(cause) = err.source() {
106
if let Some(err) = cause.downcast_ref::<ErrorCode>() {
107
return err.clone();
108
}
109
}
110
111
tracing::warn!("hyper response error: {err:?}");
112
113
ErrorCode::HttpProtocolError
114
}
115
116