1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::{HeaderName, Status, Version};
use std::{num::TryFromIntError, str::Utf8Error, time::Duration};
use thiserror::Error;
/// Concrete errors that occur within trillium's HTTP implementation
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
/// [`std::io::Error`]
#[error(transparent)]
Io(#[from] std::io::Error),
/// this error describes a malformed request with a path that does
/// not start with / or http:// or https://
#[error("Unexpected uri format")]
UnexpectedUriFormat,
/// the relevant HTTP protocol expected this header, but it was
/// not provided
#[error("Mandatory {0} header missing")]
HeaderMissing(HeaderName<'static>),
/// this error describes a request that does not specify a path
#[error("Request path missing")]
RequestPathMissing,
/// connection was closed
#[error("Connection closed by client")]
Closed,
/// [`TryFromIntError`]
#[error(transparent)]
TryFromIntError(#[from] TryFromIntError),
/// An incomplete or invalid HTTP head
#[error("Partial or invalid HTTP head")]
InvalidHead,
/// We were unable to parse a [`HeaderName`][crate::HeaderName]
#[error("Invalid or unparseable header name")]
InvalidHeaderName,
/// We were unable to parse a [`HeaderValue`][crate::HeaderValue]
#[error("Invalid or unparseable header value, header name: {0}")]
InvalidHeaderValue(HeaderName<'static>),
/// we were able to parse this [`Version`], but we do not support it
#[error("Unsupported version {0}")]
UnsupportedVersion(Version),
/// We were unable to parse a [`Version`]
#[error("Invalid or missing version")]
InvalidVersion,
/// we were unable to parse this method
#[error("Unsupported method {0}")]
UnrecognizedMethod(String),
/// this request did not have a method
#[error("Missing method")]
MissingMethod,
/// the request carried an `Expect` value that we do not handle
#[error("Unsupported expectation")]
ExpectationFailed,
/// this request did not have a status code
#[error("Missing status code")]
MissingStatus,
/// we were unable to parse a [`Status`](crate::Status)
#[error("Invalid status code")]
InvalidStatus,
/// we expected utf8, but there was an encoding error
#[error(transparent)]
EncodingError(#[from] Utf8Error),
/// we either received a header that does not make sense in context
#[error("Unexpected header: {0}")]
UnexpectedHeader(HeaderName<'static>),
/// to mitigate against malicious HTTP clients, we do not allow request headers beyond this
/// length.
#[error("Headers were malformed or longer than allowed")]
HeadersTooLong,
/// to mitigate against malicious HTTP clients, we do not read received bodies beyond this
/// length to memory. If you need to receive longer bodies, use the Stream or `AsyncRead`
/// implementation on `ReceivedBody`
#[error("Received body too long. Maximum {0} bytes")]
ReceivedBodyTooLong(u64),
/// something took longer than was allowed
#[error("{0} took longer than {1:?}")]
TimedOut(&'static str, Duration),
/// HTTP/2 peer has not advertised `SETTINGS_ENABLE_CONNECT_PROTOCOL = 1`, so an
/// extended-CONNECT request cannot be sent on this connection.
#[error("HTTP/2 peer does not support extended CONNECT")]
ExtendedConnectUnsupported,
/// An error from middleware or other application-level code, type-erased into a boxed
/// error so it can flow through the protocol error type.
///
/// Use `error.downcast_ref::<MyError>()` to recover the concrete type — for example,
/// `error.downcast_ref::<trillium_redirect::client::RedirectError>()` to inspect a
/// follow-redirects failure.
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl From<&Error> for Status {
fn from(error: &Error) -> Self {
match error {
Error::UnrecognizedMethod(_) => Status::NotImplemented,
Error::ExpectationFailed => Status::ExpectationFailed,
Error::Other(_) => Status::InternalServerError,
_ => Status::BadRequest,
}
}
}
/// this crate's result type
pub type Result<T, E = Error> = std::result::Result<T, E>;
impl Error {
/// Construct an Other variant
pub fn other(error: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::Other(Box::new(error))
}
}