Skip to main content

eggress_protocol_http/
error.rs

1/// Error types for HTTP proxy protocol operations.
2#[derive(Debug, thiserror::Error)]
3pub enum HttpError {
4    #[error("IO error: {0}")]
5    Io(#[from] std::io::Error),
6
7    #[error("malformed request: {0}")]
8    MalformedRequest(String),
9
10    #[error("malformed response: {0}")]
11    MalformedResponse(String),
12
13    #[error("unsupported HTTP version: {0}")]
14    UnsupportedVersion(String),
15
16    #[error("missing required header: {0}")]
17    MissingHeader(String),
18
19    #[error("invalid header value: {0}")]
20    InvalidHeaderValue(String),
21
22    #[error("header too large")]
23    HeaderTooLarge,
24
25    #[error("too many header lines")]
26    TooManyHeaders,
27
28    #[error("target address parse error: {0}")]
29    TargetParseError(String),
30
31    #[error("authentication required (407 Proxy Authentication Required)")]
32    AuthRequired,
33
34    #[error("authentication failed (403 Forbidden)")]
35    AuthFailed,
36
37    #[error("connection refused by upstream")]
38    ConnectionRefused,
39
40    #[error("gateway timeout (504)")]
41    GatewayTimeout,
42
43    #[error("bad gateway (502)")]
44    BadGateway,
45
46    #[error("unexpected status code: {0}")]
47    UnexpectedStatus(u16),
48
49    #[error("upstream error: {0}")]
50    Upstream(String),
51
52    #[error("invalid Content-Length header")]
53    InvalidContentLength,
54
55    #[error("conflicting Content-Length values")]
56    ConflictingContentLength,
57
58    #[error("Transfer-Encoding with Content-Length is not allowed")]
59    TransferEncodingWithContentLength,
60
61    #[error("unsupported transfer encoding: {0}")]
62    UnsupportedTransferEncoding(String),
63
64    #[error("chunked transfer encoding must be the final coding")]
65    ChunkedNotFinal,
66
67    #[error("invalid credentials: control characters not allowed")]
68    InvalidCredentials,
69
70    #[error("HTTP expectation is not supported")]
71    ExpectationFailed,
72
73    #[error("HTTP protocol upgrade is not supported")]
74    UpgradeUnsupported,
75
76    #[error("too many informational responses")]
77    TooManyInformationalResponses,
78}
79
80impl HttpError {
81    /// Returns the appropriate HTTP status code for this error.
82    pub fn status_code(&self) -> u16 {
83        match self {
84            HttpError::MalformedRequest(_) => 400,
85            HttpError::AuthRequired => 407,
86            HttpError::AuthFailed => 403,
87            HttpError::ConnectionRefused => 502,
88            HttpError::BadGateway => 502,
89            HttpError::GatewayTimeout => 504,
90            HttpError::HeaderTooLarge => 431,
91            HttpError::TooManyHeaders => 431,
92            HttpError::InvalidContentLength => 400,
93            HttpError::ConflictingContentLength => 400,
94            HttpError::TransferEncodingWithContentLength => 400,
95            HttpError::UnsupportedTransferEncoding(_) => 400,
96            HttpError::ChunkedNotFinal => 400,
97            HttpError::InvalidCredentials => 400,
98            HttpError::ExpectationFailed => 417,
99            HttpError::UpgradeUnsupported => 501,
100            HttpError::TooManyInformationalResponses => 502,
101            _ => 500,
102        }
103    }
104}