1
//! Helpers for reporting Arti errors via HTTP protocols.
2

            
3
use super::ErrorKind;
4
use http::StatusCode;
5

            
6
impl ErrorKind {
7
    /// Return an HTTP status code corresponding to this `ErrorKind`.
8
    ///
9
    /// These HTTP status codes are used by Arti in reply to client requests
10
    /// on the HTTP CONNECT proxy port.
11
    ///
12
    /// The specific status code for a given ErrorKind is _not_ formally specified.
13
    /// As such, it is okay to change them to be more appropriate.
14
    /// These codes are not guaranteed to be the same across different versions of `tor-error`.
15
    //
16
    // NOTE: One reason this method is in `tor-error` is to ensure that the match can remain
17
    // exhaustive.  Don't add a `_ =>` at the end!
18
    pub fn http_status_code(self) -> StatusCode {
19
        use ErrorKind as EK;
20
        use http::StatusCode as SC;
21
        match self {
22
            EK::ArtiShuttingDown
23
            | EK::BadApiUsage
24
            | EK::BootstrapRequired
25
            | EK::CacheAccessFailed
26
            | EK::CacheCorrupted
27
            | EK::ClockSkew
28
            | EK::DirectoryExpired
29
            | EK::ExternalToolFailed
30
            | EK::FsPermissions
31
            | EK::Internal
32
            | EK::InvalidConfig
33
            | EK::InvalidConfigTransition
34
            | EK::KeystoreAccessFailed
35
            | EK::KeystoreCorrupted
36
            | EK::NoHomeDirectory
37
            | EK::Other
38
            | EK::PersistentStateAccessFailed
39
            | EK::PersistentStateCorrupted
40
            | EK::SoftwareDeprecated
41
            | EK::TorDirectoryUnusable
42
            | EK::TransientFailure
43
            | EK::ReactorShuttingDown
44
            | EK::RelayIdMismatch
45
            | EK::RelayTooBusy
46
            | EK::TorAccessFailed
47
            | EK::TorDirectoryError => SC::INTERNAL_SERVER_ERROR,
48

            
49
            EK::FeatureDisabled | EK::NotImplemented => SC::NOT_IMPLEMENTED,
50

            
51
            EK::CircuitCollapse
52
            | EK::CircuitRefused
53
            | EK::ExitPolicyRejected
54
            | EK::LocalNetworkError
55
            | EK::LocalProtocolViolation
56
            | EK::LocalResourceAlreadyInUse
57
            | EK::LocalResourceExhausted
58
            | EK::NoExit
59
            | EK::NoPath => SC::SERVICE_UNAVAILABLE,
60

            
61
            EK::TorProtocolViolation | EK::RemoteProtocolViolation | EK::RemoteNetworkFailed => {
62
                SC::BAD_GATEWAY
63
            }
64

            
65
            EK::ExitTimeout | EK::TorNetworkTimeout | EK::RemoteNetworkTimeout => {
66
                SC::GATEWAY_TIMEOUT
67
            }
68

            
69
            EK::ForbiddenStreamTarget => SC::FORBIDDEN,
70

            
71
            EK::OnionServiceAddressInvalid | EK::InvalidStreamTarget => SC::BAD_REQUEST,
72
            EK::OnionServiceWrongClientAuth => SC::FORBIDDEN,
73
            EK::OnionServiceConnectionFailed
74
            | EK::OnionServiceMissingClientAuth
75
            | EK::OnionServiceNotFound
76
            | EK::OnionServiceNotRunning
77
            | EK::OnionServiceProtocolViolation => SC::SERVICE_UNAVAILABLE,
78

            
79
            EK::RemoteConnectionRefused
80
            | EK::RemoteHostNotFound
81
            | EK::RemoteHostResolutionFailed
82
            | EK::RemoteStreamClosed
83
            | EK::RemoteStreamError
84
            | EK::RemoteStreamReset => SC::SERVICE_UNAVAILABLE,
85
            //
86
            // NOTE: Do not add a `_ =>` catch-all here; see NOTE above.
87
        }
88
    }
89
}