mithril_aggregator/http_server/routes/
root_routes.rs1use super::middlewares;
2use crate::http_server::routes::router::RouterState;
3use warp::Filter;
4
5pub fn routes(
6 router_state: &RouterState,
7) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
8 root(router_state)
9}
10
11fn root(
13 router_state: &RouterState,
14) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
15 warp::path::end()
16 .and(middlewares::with_logger(router_state))
17 .and(middlewares::with_api_version_provider(router_state))
18 .and(middlewares::extract_config(router_state, |config| {
19 config.allowed_discriminants.clone()
20 }))
21 .and(middlewares::extract_config(router_state, |config| {
22 config.cardano_transactions_prover_max_hashes_allowed_by_request
23 }))
24 .and_then(handlers::root)
25}
26
27mod handlers {
28 use std::collections::BTreeSet;
29 use std::{convert::Infallible, sync::Arc};
30
31 use slog::Logger;
32 use warp::http::StatusCode;
33
34 use mithril_common::api_version::APIVersionProvider;
35 use mithril_common::entities::SignedEntityTypeDiscriminants;
36 use mithril_common::messages::{
37 AggregatorCapabilities, AggregatorFeaturesMessage, CardanoTransactionsProverCapabilities,
38 };
39
40 use crate::http_server::routes::reply::json;
41 use crate::unwrap_to_internal_server_error;
42
43 pub async fn root(
45 logger: Logger,
46 api_version_provider: Arc<APIVersionProvider>,
47 allowed_signed_entity_type_discriminants: BTreeSet<SignedEntityTypeDiscriminants>,
48 max_hashes_allowed_by_request: usize,
49 ) -> Result<impl warp::Reply, Infallible> {
50 let open_api_version = unwrap_to_internal_server_error!(
51 api_version_provider.compute_current_version(),
52 logger => "root::error"
53 );
54
55 let mut capabilities = AggregatorCapabilities {
56 signed_entity_types: allowed_signed_entity_type_discriminants,
57 cardano_transactions_prover: None,
58 };
59
60 if capabilities
61 .signed_entity_types
62 .contains(&SignedEntityTypeDiscriminants::CardanoTransactions)
63 {
64 capabilities.cardano_transactions_prover =
65 Some(CardanoTransactionsProverCapabilities {
66 max_hashes_allowed_by_request,
67 });
68 }
69
70 Ok(json(
71 &AggregatorFeaturesMessage {
72 open_api_version: open_api_version.to_string(),
73 documentation_url: env!("CARGO_PKG_HOMEPAGE").to_string(),
74 capabilities,
75 },
76 StatusCode::OK,
77 ))
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::http_server::routes::router::RouterConfig;
84 use crate::initialize_dependencies;
85 use mithril_common::entities::SignedEntityTypeDiscriminants;
86 use mithril_common::messages::{
87 AggregatorCapabilities, AggregatorFeaturesMessage, CardanoTransactionsProverCapabilities,
88 };
89 use mithril_common::test_utils::apispec::APISpec;
90 use serde_json::Value::Null;
91 use std::collections::BTreeSet;
92 use std::sync::Arc;
93 use warp::http::Method;
94 use warp::http::StatusCode;
95 use warp::test::request;
96 use warp::Filter;
97
98 use super::*;
99
100 fn setup_router(
101 state: RouterState,
102 ) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
103 let cors = warp::cors()
104 .allow_any_origin()
105 .allow_headers(vec!["content-type"])
106 .allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
107
108 warp::any().and(routes(&state).with(cors))
109 }
110
111 #[tokio::test]
112 async fn test_root_route_ok() {
113 let method = Method::GET.as_str();
114 let path = "/";
115 let config = RouterConfig {
116 allowed_discriminants: BTreeSet::from([
117 SignedEntityTypeDiscriminants::CardanoStakeDistribution,
118 SignedEntityTypeDiscriminants::CardanoImmutableFilesFull,
119 SignedEntityTypeDiscriminants::MithrilStakeDistribution,
120 ]),
121 ..RouterConfig::dummy()
122 };
123 let dependency_manager = initialize_dependencies!().await;
124
125 let expected_open_api_version = dependency_manager
126 .api_version_provider
127 .clone()
128 .compute_current_version()
129 .unwrap()
130 .to_string();
131
132 let response = request()
133 .method(method)
134 .path(path)
135 .reply(&setup_router(RouterState::new(
136 Arc::new(dependency_manager),
137 config,
138 )))
139 .await;
140
141 let response_body: AggregatorFeaturesMessage =
142 serde_json::from_slice(response.body()).unwrap();
143
144 assert_eq!(response.status(), StatusCode::OK);
145
146 assert_eq!(
147 response_body,
148 AggregatorFeaturesMessage {
149 open_api_version: expected_open_api_version,
150 documentation_url: env!("CARGO_PKG_HOMEPAGE").to_string(),
151 capabilities: AggregatorCapabilities {
152 signed_entity_types: BTreeSet::from_iter([
153 SignedEntityTypeDiscriminants::CardanoStakeDistribution,
154 SignedEntityTypeDiscriminants::CardanoImmutableFilesFull,
155 SignedEntityTypeDiscriminants::MithrilStakeDistribution,
156 ]),
157 cardano_transactions_prover: None,
158 },
159 }
160 );
161
162 APISpec::verify_conformity(
163 APISpec::get_all_spec_files(),
164 method,
165 path,
166 "application/json",
167 &Null,
168 &response,
169 &StatusCode::OK,
170 )
171 .unwrap();
172 }
173
174 #[tokio::test]
175 async fn test_root_route_ok_with_cardano_transactions_enabled() {
176 let method = Method::GET.as_str();
177 let path = "/";
178 let config = RouterConfig {
179 allowed_discriminants: BTreeSet::from([
180 SignedEntityTypeDiscriminants::CardanoTransactions,
181 ]),
182 cardano_transactions_prover_max_hashes_allowed_by_request: 99,
183 ..RouterConfig::dummy()
184 };
185 let dependency_manager = initialize_dependencies!().await;
186
187 let response = request()
188 .method(method)
189 .path(path)
190 .reply(&setup_router(RouterState::new(
191 Arc::new(dependency_manager),
192 config,
193 )))
194 .await;
195
196 let response_body: AggregatorFeaturesMessage =
197 serde_json::from_slice(response.body()).unwrap();
198
199 assert_eq!(response.status(), StatusCode::OK);
200
201 assert_eq!(
202 response_body.capabilities.cardano_transactions_prover,
203 Some(CardanoTransactionsProverCapabilities {
204 max_hashes_allowed_by_request: 99
205 })
206 );
207
208 APISpec::verify_conformity(
209 APISpec::get_all_spec_files(),
210 method,
211 path,
212 "application/json",
213 &Null,
214 &response,
215 &StatusCode::OK,
216 )
217 .unwrap();
218 }
219}