mithril_aggregator/http_server/routes/
epoch_routes.rs

1use 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
12/// GET /epoch-settings
13fn 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    /// Epoch Settings
39    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}