Skip to content

Commit 4a5a989

Browse files
committed
add signer version error message
1 parent 2aa5ca3 commit 4a5a989

File tree

1 file changed

+105
-3
lines changed

1 file changed

+105
-3
lines changed

mithril-signer/src/certificate_handler.rs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use async_trait::async_trait;
2-
use reqwest::{self, Client, RequestBuilder, StatusCode};
2+
use reqwest::{self, Client, RequestBuilder, Response, StatusCode};
33
use slog_scope::debug;
44
use std::io;
55
use thiserror::Error;
@@ -35,6 +35,21 @@ pub enum CertificateHandlerError {
3535
/// Mostly network errors.
3636
#[error("io error: {0}")]
3737
IOError(#[from] io::Error),
38+
39+
/// Incompatible API version error
40+
#[error("HTTP API version mismatch: {0}")]
41+
ApiVersionMismatch(String),
42+
}
43+
44+
#[cfg(test)]
45+
/// convenient methods to error enum
46+
impl CertificateHandlerError {
47+
pub fn is_api_version_mismatch(&self) -> bool {
48+
match self {
49+
Self::ApiVersionMismatch(_) => true,
50+
_ => false,
51+
}
52+
}
3853
}
3954

4055
/// Trait for mocking and testing a `CertificateHandler`
@@ -79,6 +94,22 @@ impl CertificateHandlerHTTPClient {
7994
pub fn prepare_request_builder(&self, request_builder: RequestBuilder) -> RequestBuilder {
8095
request_builder.header("API_VERSION", MITHRIL_API_VERSION)
8196
}
97+
98+
/// API version error handling
99+
fn handle_api_error(&self, response: &Response) -> CertificateHandlerError {
100+
if let Some(version) = response.headers().get("mithril-api-version") {
101+
CertificateHandlerError::ApiVersionMismatch(format!(
102+
"server version: '{}', signer version: '{}'",
103+
version.to_str().unwrap(),
104+
MITHRIL_API_VERSION
105+
))
106+
} else {
107+
CertificateHandlerError::ApiVersionMismatch(format!(
108+
"version precondition failed, sent version '{}'.",
109+
MITHRIL_API_VERSION
110+
))
111+
}
112+
}
82113
}
83114

84115
#[async_trait]
@@ -99,6 +130,7 @@ impl CertificateHandler for CertificateHandlerHTTPClient {
99130
Ok(epoch_settings) => Ok(Some(epoch_settings)),
100131
Err(err) => Err(CertificateHandlerError::JsonParseFailed(err.to_string())),
101132
},
133+
StatusCode::PRECONDITION_FAILED => Err(self.handle_api_error(&response)),
102134
_ => Err(CertificateHandlerError::RemoteServerTechnical(
103135
response.text().await.unwrap_or_default(),
104136
)),
@@ -125,6 +157,7 @@ impl CertificateHandler for CertificateHandlerHTTPClient {
125157
Ok(pending_certificate) => Ok(Some(pending_certificate)),
126158
Err(err) => Err(CertificateHandlerError::JsonParseFailed(err.to_string())),
127159
},
160+
StatusCode::PRECONDITION_FAILED => Err(self.handle_api_error(&response)),
128161
StatusCode::NO_CONTENT => Ok(None),
129162
_ => Err(CertificateHandlerError::RemoteServerTechnical(
130163
response.text().await.unwrap_or_default(),
@@ -148,6 +181,7 @@ impl CertificateHandler for CertificateHandlerHTTPClient {
148181
match response {
149182
Ok(response) => match response.status() {
150183
StatusCode::CREATED => Ok(()),
184+
StatusCode::PRECONDITION_FAILED => Err(self.handle_api_error(&response)),
151185
StatusCode::BAD_REQUEST => Err(CertificateHandlerError::RemoteServerLogical(
152186
format!("bad request: {}", response.text().await.unwrap_or_default()),
153187
)),
@@ -176,6 +210,7 @@ impl CertificateHandler for CertificateHandlerHTTPClient {
176210
match response {
177211
Ok(response) => match response.status() {
178212
StatusCode::CREATED => Ok(()),
213+
StatusCode::PRECONDITION_FAILED => Err(self.handle_api_error(&response)),
179214
StatusCode::BAD_REQUEST => Err(CertificateHandlerError::RemoteServerLogical(
180215
format!("bad request: {}", response.text().await.unwrap_or_default()),
181216
)),
@@ -325,6 +360,22 @@ mod tests {
325360
assert_eq!(epoch_settings_expected, epoch_settings.unwrap().unwrap());
326361
}
327362

363+
#[tokio::test]
364+
async fn test_epoch_settings_ko_412() {
365+
let (server, config) = setup_test();
366+
let _snapshots_mock = server.mock(|when, then| {
367+
when.path("/epoch-settings");
368+
then.status(412).header("mithril-api-version", "0.0.999");
369+
});
370+
let certificate_handler = CertificateHandlerHTTPClient::new(config.aggregator_endpoint);
371+
let epoch_settings = certificate_handler
372+
.retrieve_epoch_settings()
373+
.await
374+
.unwrap_err();
375+
376+
assert!(epoch_settings.is_api_version_mismatch());
377+
}
378+
328379
#[tokio::test]
329380
async fn test_epoch_settings_ko_500() {
330381
let (server, config) = setup_test();
@@ -359,6 +410,22 @@ mod tests {
359410
);
360411
}
361412

413+
#[tokio::test]
414+
async fn test_certificate_pending_ko_412() {
415+
let (server, config) = setup_test();
416+
let _snapshots_mock = server.mock(|when, then| {
417+
when.path("/certificate-pending");
418+
then.status(412).header("mithril-api-version", "0.0.999");
419+
});
420+
let certificate_handler = CertificateHandlerHTTPClient::new(config.aggregator_endpoint);
421+
let error = certificate_handler
422+
.retrieve_pending_certificate()
423+
.await
424+
.unwrap_err();
425+
426+
assert!(error.is_api_version_mismatch());
427+
}
428+
362429
#[tokio::test]
363430
async fn test_certificate_pending_ok_204() {
364431
let (server, config) = setup_test();
@@ -402,7 +469,25 @@ mod tests {
402469
}
403470

404471
#[tokio::test]
405-
async fn test_register_signer_ok_400() {
472+
async fn test_register_signer_ko_412() {
473+
let (server, config) = setup_test();
474+
let _snapshots_mock = server.mock(|when, then| {
475+
when.method(POST).path("/register-signer");
476+
then.status(412).header("mithril-api-version", "0.0.999");
477+
});
478+
let single_signers = fake_data::signers(1);
479+
let single_signer = single_signers.first().unwrap();
480+
let certificate_handler = CertificateHandlerHTTPClient::new(config.aggregator_endpoint);
481+
let error = certificate_handler
482+
.register_signer(single_signer)
483+
.await
484+
.unwrap_err();
485+
486+
assert!(error.is_api_version_mismatch());
487+
}
488+
489+
#[tokio::test]
490+
async fn test_register_signer_ko_400() {
406491
let single_signers = fake_data::signers(1);
407492
let single_signer = single_signers.first().unwrap();
408493
let (server, config) = setup_test();
@@ -428,7 +513,7 @@ mod tests {
428513
}
429514

430515
#[tokio::test]
431-
async fn test_register_signer_ok_500() {
516+
async fn test_register_signer_ko_500() {
432517
let single_signers = fake_data::signers(1);
433518
let single_signer = single_signers.first().unwrap();
434519
let (server, config) = setup_test();
@@ -460,6 +545,23 @@ mod tests {
460545
register_signatures.expect("unexpected error");
461546
}
462547

548+
#[tokio::test]
549+
async fn test_register_signatures_ko_412() {
550+
let (server, config) = setup_test();
551+
let _snapshots_mock = server.mock(|when, then| {
552+
when.method(POST).path("/register-signatures");
553+
then.status(412).header("mithril-api-version", "0.0.999");
554+
});
555+
let single_signatures = fake_data::single_signatures((1..5).collect());
556+
let certificate_handler = CertificateHandlerHTTPClient::new(config.aggregator_endpoint);
557+
let error = certificate_handler
558+
.register_signatures(&single_signatures)
559+
.await
560+
.unwrap_err();
561+
562+
assert!(error.is_api_version_mismatch());
563+
}
564+
463565
#[tokio::test]
464566
async fn test_register_signatures_ko_400() {
465567
let single_signatures = fake_data::single_signatures((1..5).collect());

0 commit comments

Comments
 (0)