diff --git a/mithril-aggregator/src/http_server/routes/router.rs b/mithril-aggregator/src/http_server/routes/router.rs index d34e1fad7e8..06832ed6264 100644 --- a/mithril-aggregator/src/http_server/routes/router.rs +++ b/mithril-aggregator/src/http_server/routes/router.rs @@ -3,6 +3,10 @@ use crate::http_server::routes::{ }; use crate::http_server::SERVER_BASE_PATH; use crate::DependencyManager; + +use mithril_common::MITHRIL_API_VERSION; + +use reqwest::header::{HeaderMap, HeaderValue}; use std::sync::Arc; use warp::http::Method; use warp::Filter; @@ -15,6 +19,11 @@ pub fn routes( .allow_any_origin() .allow_headers(vec!["content-type"]) .allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]); + let mut headers = HeaderMap::new(); + headers.insert( + "mithril-api-version", + HeaderValue::from_static(MITHRIL_API_VERSION), + ); warp::any().and(warp::path(SERVER_BASE_PATH)).and( certificate_routes::routes(dependency_manager.clone()) @@ -22,6 +31,7 @@ pub fn routes( .or(signer_routes::routes(dependency_manager.clone())) .or(signatures_routes::routes(dependency_manager.clone())) .or(epoch_routes::routes(dependency_manager)) - .with(cors), + .with(cors) + .with(warp::reply::with::headers(headers)), ) } diff --git a/mithril-client/src/aggregator.rs b/mithril-client/src/aggregator.rs index fee36ddd037..bac0c9bed25 100644 --- a/mithril-client/src/aggregator.rs +++ b/mithril-client/src/aggregator.rs @@ -2,6 +2,7 @@ use async_trait::async_trait; use flate2::read::GzDecoder; use futures::StreamExt; use reqwest::{self, StatusCode}; +use reqwest::{Client, RequestBuilder}; use slog_scope::debug; use std::env; use std::fs; @@ -12,7 +13,10 @@ use std::sync::Arc; use tar::Archive; use thiserror::Error; -use mithril_common::entities::{Certificate, Snapshot}; +use mithril_common::{ + entities::{Certificate, Snapshot}, + MITHRIL_API_VERSION, +}; use mithril_common::certificate_chain::CertificateRetriever; use mithril_common::certificate_chain::CertificateRetrieverError; @@ -86,6 +90,11 @@ impl AggregatorHTTPClient { } } + /// Forge a client request adding protocol version in the headers. + pub fn prepare_request_builder(&self, request_builder: RequestBuilder) -> RequestBuilder { + request_builder.header("API_VERSION", MITHRIL_API_VERSION) + } + /// Download certificate details async fn download_certificate_details( &self, @@ -96,7 +105,11 @@ impl AggregatorHTTPClient { "{}/certificate/{}", self.aggregator_endpoint, certificate_hash ); - let response = reqwest::get(url.clone()).await; + let response = self + .prepare_request_builder(Client::new().get(url.clone())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => match response.json::().await { @@ -123,7 +136,11 @@ impl AggregatorHandler for AggregatorHTTPClient { async fn list_snapshots(&self) -> Result, AggregatorHandlerError> { debug!("List snapshots"); let url = format!("{}/snapshots", self.aggregator_endpoint); - let response = reqwest::get(url.clone()).await; + let response = self + .prepare_request_builder(Client::new().get(url.clone())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => match response.json::>().await { @@ -144,7 +161,11 @@ impl AggregatorHandler for AggregatorHTTPClient { async fn get_snapshot_details(&self, digest: &str) -> Result { debug!("Details snapshot {}", digest); let url = format!("{}/snapshot/{}", self.aggregator_endpoint, digest); - let response = reqwest::get(url.clone()).await; + let response = self + .prepare_request_builder(Client::new().get(url.clone())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => match response.json::().await { @@ -171,7 +192,11 @@ impl AggregatorHandler for AggregatorHTTPClient { location: &str, ) -> Result { debug!("Download snapshot {} from {}", digest, location); - let response = reqwest::get(location).await; + let response = self + .prepare_request_builder(Client::new().get(location.to_owned())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => { diff --git a/mithril-common/src/lib.rs b/mithril-common/src/lib.rs index a53b9676a97..49542780759 100644 --- a/mithril-common/src/lib.rs +++ b/mithril-common/src/lib.rs @@ -35,3 +35,9 @@ pub const NEXT_SIGNER_EPOCH_RETRIEVAL_OFFSET: i64 = 0; /// The epoch offset used for signers stake distribution and verification keys recording. pub const SIGNER_EPOCH_RECORDING_OFFSET: i64 = 1; + +/// Mithril API protocol version +/// this is the same as the one in openapi.yml file. +/// If you want to update this version to reflect changes in the protocol, +/// please also update the entry in the openapi.yml +pub const MITHRIL_API_VERSION: &str = "0.0.1"; diff --git a/mithril-signer/src/certificate_handler.rs b/mithril-signer/src/certificate_handler.rs index bf09a6059fe..e66b6b3ea7b 100644 --- a/mithril-signer/src/certificate_handler.rs +++ b/mithril-signer/src/certificate_handler.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use reqwest::{self, StatusCode}; +use reqwest::{self, Client, RequestBuilder, StatusCode}; use slog_scope::debug; use std::io; use thiserror::Error; @@ -7,7 +7,7 @@ use tokio::sync::RwLock; use mithril_common::{ entities::{CertificatePending, EpochSettings, Signer, SingleSignatures}, - fake_data, + fake_data, MITHRIL_API_VERSION, }; #[cfg(test)] @@ -74,6 +74,11 @@ impl CertificateHandlerHTTPClient { aggregator_endpoint, } } + + /// Forge a client request adding protocol version in the headers. + pub fn prepare_request_builder(&self, request_builder: RequestBuilder) -> RequestBuilder { + request_builder.header("API_VERSION", MITHRIL_API_VERSION) + } } #[async_trait] @@ -83,7 +88,11 @@ impl CertificateHandler for CertificateHandlerHTTPClient { ) -> Result, CertificateHandlerError> { debug!("Retrieve epoch settings"); let url = format!("{}/epoch-settings", self.aggregator_endpoint); - let response = reqwest::get(url.clone()).await; + let response = self + .prepare_request_builder(Client::new().get(url.clone())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => match response.json::().await { @@ -105,7 +114,11 @@ impl CertificateHandler for CertificateHandlerHTTPClient { ) -> Result, CertificateHandlerError> { debug!("Retrieve pending certificate"); let url = format!("{}/certificate-pending", self.aggregator_endpoint); - let response = reqwest::get(url.clone()).await; + let response = self + .prepare_request_builder(Client::new().get(url.clone())) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::OK => match response.json::().await { @@ -126,8 +139,12 @@ impl CertificateHandler for CertificateHandlerHTTPClient { async fn register_signer(&self, signer: &Signer) -> Result<(), CertificateHandlerError> { debug!("Register signer"); let url = format!("{}/register-signer", self.aggregator_endpoint); - let client = reqwest::Client::new(); - let response = client.post(url.clone()).json(signer).send().await; + let response = self + .prepare_request_builder(Client::new().post(url.clone())) + .json(signer) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::CREATED => Ok(()), @@ -150,8 +167,12 @@ impl CertificateHandler for CertificateHandlerHTTPClient { ) -> Result<(), CertificateHandlerError> { debug!("Register signatures"); let url = format!("{}/register-signatures", self.aggregator_endpoint); - let client = reqwest::Client::new(); - let response = client.post(url.clone()).json(signatures).send().await; + let response = self + .prepare_request_builder(Client::new().post(url.clone())) + .json(signatures) + .send() + .await; + match response { Ok(response) => match response.status() { StatusCode::CREATED => Ok(()), diff --git a/openapi.yaml b/openapi.yaml index d96897da9b2..4ae65287a63 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1,5 +1,9 @@ openapi: "3.0.0" info: + # The protocol version is embedded in the code as constant in the + # `mithril-aggregator/src/http_server/mod.rs` file. If you plan to update it + # here to reflect changes in the API, please also update the constant in the + # Rust file. version: 0.0.1 title: Mithril Aggregator Server description: |