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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
use apollo_errors::Error;
use apollo_errors::miette;
use tower::BoxError;
/// Errors produced by the HTTP client.
#[non_exhaustive]
#[derive(Debug, Error, miette::Diagnostic)]
pub enum HttpClientError {
/// The HTTP client could not be constructed.
#[error("failed to build HTTP client")]
#[diagnostic(code(http_client::build_failed))]
Build {
/// The underlying error.
#[from]
source: rustls::Error,
},
/// `tls.certificate_authorities` could not be parsed as PEM.
#[error("failed to parse `tls.certificate_authorities` as PEM")]
#[diagnostic(code(http_client::tls_certificate_authorities_invalid))]
TlsCertificateAuthoritiesInvalid {
/// The underlying error.
#[source]
source: std::io::Error,
},
/// `tls.certificate_authorities` contained no PEM certificate blocks.
#[error("`tls.certificate_authorities` contained no certificates")]
#[diagnostic(code(http_client::tls_certificate_authorities_empty))]
TlsCertificateAuthoritiesEmpty,
/// TLS verification is enabled but no trust anchors are configured.
#[error(
"TLS has no trust anchors: set `tls.certificate_authorities`, enable \
`tls.use_native_certificate_store`, or set `tls.danger_accept_invalid_certs` \
for development only"
)]
#[diagnostic(code(http_client::tls_no_trust_anchors))]
TlsNoTrustAnchors,
/// `tls.client_authentication.certificate_chain` could not be parsed as PEM.
#[error("failed to parse `tls.client_authentication.certificate_chain` as PEM")]
#[diagnostic(code(http_client::tls_client_certificate_chain_invalid))]
TlsClientCertificateChainInvalid {
/// The underlying error.
#[source]
source: std::io::Error,
},
/// `tls.client_authentication.certificate_chain` contained no certificates.
#[error("`tls.client_authentication.certificate_chain` contained no certificates")]
#[diagnostic(code(http_client::tls_client_certificate_chain_empty))]
TlsClientCertificateChainEmpty,
/// `tls.client_authentication.key` could not be parsed as PEM.
#[error("failed to parse `tls.client_authentication.key` as PEM")]
#[diagnostic(code(http_client::tls_client_key_invalid))]
TlsClientKeyInvalid {
/// The underlying error.
#[source]
source: std::io::Error,
},
/// `tls.client_authentication.key` contained no recognised private key block.
#[error(
"`tls.client_authentication.key` contained no PKCS#1, PKCS#8, or SEC1 private key block"
)]
#[diagnostic(code(http_client::tls_client_key_missing))]
TlsClientKeyMissing,
/// `tls.client_authentication.key` is encrypted. Encrypted keys are not supported.
#[error(
"`tls.client_authentication.key` is encrypted; only unencrypted private keys are supported"
)]
#[diagnostic(code(http_client::tls_client_key_encrypted))]
TlsClientKeyEncrypted,
/// `tls.client_authentication` was rejected by rustls — typically because
/// the private key is not usable as a TLS signer or does not match the
/// leaf certificate's public key.
///
/// Cert/key pair mismatches that pass the build but fail the handshake
/// surface as [`Transport`](Self::Transport).
#[error(
"failed to configure TLS client authentication from `tls.client_authentication` \
— verify `certificate_chain` and `key` are from the same key pair"
)]
#[diagnostic(code(http_client::tls_client_auth))]
TlsClientAuth {
/// The underlying error.
#[source]
source: rustls::Error,
},
/// The request URI could not be constructed from its components.
#[error("invalid request URI")]
#[diagnostic(code(http_client::invalid_uri))]
InvalidUri {
/// The underlying error.
#[source]
source: http::Error,
},
/// The connection timed out before being established.
#[error("connection timed out")]
#[diagnostic(code(http_client::connection_timeout))]
ConnectionTimeout,
/// A TCP or TLS transport error.
#[error("transport error")]
#[diagnostic(code(http_client::transport_error))]
Transport {
/// The underlying error.
#[source]
source: BoxError,
},
/// The HTTP/1.1 or HTTP/2 handshake failed.
#[error("HTTP handshake failed")]
#[diagnostic(code(http_client::handshake_failed))]
Handshake {
/// The underlying error.
#[source]
source: hyper::Error,
},
/// Sending or receiving the HTTP request failed.
#[error("HTTP request failed")]
#[diagnostic(code(http_client::request_failed))]
Request {
/// The underlying error.
#[source]
source: hyper::Error,
},
/// The proxy returned a non-200 response to a CONNECT request.
#[error("proxy CONNECT rejected with status {status}")]
#[diagnostic(code(http_client::proxy_connect_rejected))]
ProxyTunnel {
/// The HTTP status code returned by the proxy.
status: http::StatusCode,
},
/// The configuration failed validation.
///
/// `apollo_configuration::parse_yaml` runs validation before returning, so
/// this only fires when the config reached [`HttpClient::new`] through a
/// path that bypassed it.
///
/// [`HttpClient::new`]: crate::HttpClient::new
#[error("invalid HTTP client configuration")]
#[diagnostic(code(http_client::invalid_config))]
InvalidConfig {
/// The collected validation errors.
#[source]
source: apollo_configuration::ValidationErrors,
},
/// A `unix://` URI's authority could not be hex-decoded into a socket path.
#[cfg(unix)]
#[error("invalid Unix socket path in URI authority")]
#[diagnostic(code(http_client::invalid_unix_socket_path))]
InvalidUnixSocketPath {
/// The underlying decoding error.
#[source]
source: hex::FromHexError,
},
/// A `unix://` URI's authority decoded to bytes that are not valid UTF-8.
///
/// Non-UTF-8 socket paths are not supported.
#[cfg(unix)]
#[error("Unix socket path is not valid UTF-8")]
#[diagnostic(code(http_client::non_utf8_unix_socket_path))]
NonUtf8UnixSocketPath {
/// The underlying UTF-8 decoding error.
#[source]
source: std::string::FromUtf8Error,
},
/// The request URI's scheme is not supported on this platform.
#[error("unsupported URI scheme: {scheme:?}")]
#[diagnostic(code(http_client::unsupported_scheme))]
UnsupportedScheme {
/// The scheme from the request URI.
scheme: String,
},
}