mithril_aggregator/http_server/routes/
epoch_routes.rs1use warp::Filter;
2
3use crate::http_server::routes::middlewares;
4use crate::http_server::routes::router::RouterState;
5
6pub fn routes(
7 router_state: &RouterState,
8) -> impl Filter<Extract = (impl warp::Reply + use<>,), Error = warp::Rejection> + Clone + use<> {
9 epoch_settings(router_state)
10}
11
12fn epoch_settings(
14 router_state: &RouterState,
15) -> impl Filter<Extract = (impl warp::Reply + use<>,), Error = warp::Rejection> + Clone + use<> {
16 warp::path!("epoch-settings")
17 .and(warp::get())
18 .and(middlewares::with_logger(router_state))
19 .and(middlewares::with_http_message_service(router_state))
20 .and(middlewares::extract_config(router_state, |config| {
21 config.allowed_discriminants.clone()
22 }))
23 .and_then(handlers::epoch_settings)
24}
25
26mod handlers {
27 use slog::{Logger, warn};
28 use std::collections::BTreeSet;
29 use std::convert::Infallible;
30 use std::sync::Arc;
31 use warp::http::StatusCode;
32
33 use mithril_common::entities::SignedEntityTypeDiscriminants;
34
35 use crate::http_server::routes::reply;
36 use crate::services::MessageService;
37
38 pub async fn epoch_settings(
40 logger: Logger,
41 http_message_service: Arc<dyn MessageService>,
42 allowed_discriminants: BTreeSet<SignedEntityTypeDiscriminants>,
43 ) -> Result<impl warp::Reply, Infallible> {
44 let epoch_settings_message = http_message_service
45 .get_epoch_settings_message(allowed_discriminants)
46 .await;
47
48 match epoch_settings_message {
49 Ok(message) => Ok(reply::json(&message, StatusCode::OK)),
50 Err(err) => {
51 warn!(logger,"epoch_settings::error"; "error" => ?err);
52 Ok(reply::server_error(err))
53 }
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use anyhow::anyhow;
61 use serde_json::Value::Null;
62 use std::sync::Arc;
63 use warp::{
64 http::{Method, StatusCode},
65 test::request,
66 };
67
68 use mithril_api_spec::APISpec;
69 use mithril_common::messages::EpochSettingsMessage;
70
71 use crate::{initialize_dependencies, services::MockMessageService};
72
73 use super::*;
74
75 fn setup_router(
76 state: RouterState,
77 ) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
78 let cors = warp::cors()
79 .allow_any_origin()
80 .allow_headers(vec!["content-type"])
81 .allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
82
83 warp::any().and(routes(&state).with(cors))
84 }
85
86 #[tokio::test]
87 async fn test_epoch_settings_get_ok() {
88 let method = Method::GET.as_str();
89 let path = "/epoch-settings";
90 let mut dependency_manager = initialize_dependencies!().await;
91 let mut mock_http_message_service = MockMessageService::new();
92 mock_http_message_service
93 .expect_get_epoch_settings_message()
94 .return_once(|_| Ok(EpochSettingsMessage::dummy()))
95 .once();
96 dependency_manager.message_service = Arc::new(mock_http_message_service);
97
98 let response = request()
99 .method(method)
100 .path(path)
101 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
102 dependency_manager,
103 ))))
104 .await;
105
106 APISpec::verify_conformity(
107 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
108 method,
109 path,
110 "application/json",
111 &Null,
112 &response,
113 &StatusCode::OK,
114 )
115 .unwrap();
116 }
117
118 #[tokio::test]
119 async fn test_epoch_settings_get_ko_500() {
120 let method = Method::GET.as_str();
121 let path = "/epoch-settings";
122 let mut dependency_manager = initialize_dependencies!().await;
123 let mut mock_http_message_service = MockMessageService::new();
124 mock_http_message_service
125 .expect_get_epoch_settings_message()
126 .return_once(|_| Err(anyhow!("an error")))
127 .once();
128 dependency_manager.message_service = Arc::new(mock_http_message_service);
129
130 let response = request()
131 .method(method)
132 .path(path)
133 .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
134 dependency_manager,
135 ))))
136 .await;
137
138 APISpec::verify_conformity(
139 APISpec::get_default_spec_file_from(crate::http_server::API_SPEC_LOCATION),
140 method,
141 path,
142 "application/json",
143 &Null,
144 &response,
145 &StatusCode::INTERNAL_SERVER_ERROR,
146 )
147 .unwrap();
148 }
149}