Skip to main content

vibeio_http/h2/
error.rs

1//! HTTP/2 error types (RFC 9113 Section 7).
2
3/// HTTP/2 error codes (RFC 9113 Section 7).
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[repr(u32)]
6pub enum Reason {
7    NoError = 0x00,
8    ProtocolError = 0x01,
9    InternalError = 0x02,
10    FlowControlError = 0x03,
11    SettingsTimeout = 0x04,
12    StreamClosed = 0x05,
13    FrameSizeError = 0x06,
14    RefusedStream = 0x07,
15    Cancel = 0x08,
16    CompressionError = 0x09,
17    ConnectError = 0x0a,
18    EnhanceYourCalm = 0x0b,
19    InadequateSecurity = 0x0c,
20    Http11Required = 0x0d,
21}
22
23impl Reason {
24    /// The numeric wire value of this error code.
25    pub const fn code(self) -> u32 {
26        self as u32
27    }
28
29    /// Looks up a wire value; unknown codes are `None` (they are
30    /// forwarded as opaque numbers by GOAWAY/RST_STREAM).
31    pub const fn from_code(code: u32) -> Option<Reason> {
32        match code {
33            0x00 => Some(Reason::NoError),
34            0x01 => Some(Reason::ProtocolError),
35            0x02 => Some(Reason::InternalError),
36            0x03 => Some(Reason::FlowControlError),
37            0x04 => Some(Reason::SettingsTimeout),
38            0x05 => Some(Reason::StreamClosed),
39            0x06 => Some(Reason::FrameSizeError),
40            0x07 => Some(Reason::RefusedStream),
41            0x08 => Some(Reason::Cancel),
42            0x09 => Some(Reason::CompressionError),
43            0x0a => Some(Reason::ConnectError),
44            0x0b => Some(Reason::EnhanceYourCalm),
45            0x0c => Some(Reason::InadequateSecurity),
46            0x0d => Some(Reason::Http11Required),
47            _ => None,
48        }
49    }
50}
51
52/// An HTTP/2 protocol error: a rule violation with the connection or
53/// stream error code to report, and a human-readable description.
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct H2Error {
56    pub reason: Reason,
57    pub message: &'static str,
58}
59
60impl H2Error {
61    /// Creates a protocol error with the given connection/stream error
62    /// code.
63    pub const fn new(reason: Reason, message: &'static str) -> H2Error {
64        H2Error { reason, message }
65    }
66
67    /// A generic protocol violation.
68    pub const fn protocol(message: &'static str) -> H2Error {
69        H2Error::new(Reason::ProtocolError, message)
70    }
71
72    /// A framing violation (oversized or malformed frame).
73    pub const fn frame_size(message: &'static str) -> H2Error {
74        H2Error::new(Reason::FrameSizeError, message)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn codes_round_trip() {
84        for reason in [
85            Reason::NoError,
86            Reason::ProtocolError,
87            Reason::InternalError,
88            Reason::FlowControlError,
89            Reason::SettingsTimeout,
90            Reason::StreamClosed,
91            Reason::FrameSizeError,
92            Reason::RefusedStream,
93            Reason::Cancel,
94            Reason::CompressionError,
95            Reason::ConnectError,
96            Reason::EnhanceYourCalm,
97            Reason::InadequateSecurity,
98            Reason::Http11Required,
99        ] {
100            assert_eq!(Reason::from_code(reason.code()), Some(reason));
101        }
102        assert_eq!(Reason::from_code(0x0e), None);
103        assert_eq!(Reason::from_code(u32::MAX), None);
104    }
105}