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,), Error = warp::Rejection> + Clone {
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,), Error = warp::Rejection> + Clone {
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::{warn, Logger};
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_common::{messages::EpochSettingsMessage, test_utils::apispec::APISpec};
69
70    use crate::{initialize_dependencies, services::MockMessageService};
71
72    use super::*;
73
74    fn setup_router(
75        state: RouterState,
76    ) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
77        let cors = warp::cors()
78            .allow_any_origin()
79            .allow_headers(vec!["content-type"])
80            .allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
81
82        warp::any().and(routes(&state).with(cors))
83    }
84
85    #[tokio::test]
86    async fn test_epoch_settings_get_ok() {
87        let method = Method::GET.as_str();
88        let path = "/epoch-settings";
89        let mut dependency_manager = initialize_dependencies!().await;
90        let mut mock_http_message_service = MockMessageService::new();
91        mock_http_message_service
92            .expect_get_epoch_settings_message()
93            .return_once(|_| Ok(EpochSettingsMessage::dummy()))
94            .once();
95        dependency_manager.message_service = Arc::new(mock_http_message_service);
96
97        let response = request()
98            .method(method)
99            .path(path)
100            .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
101                dependency_manager,
102            ))))
103            .await;
104
105        APISpec::verify_conformity(
106            APISpec::get_all_spec_files(),
107            method,
108            path,
109            "application/json",
110            &Null,
111            &response,
112            &StatusCode::OK,
113        )
114        .unwrap();
115    }
116
117    #[tokio::test]
118    async fn test_epoch_settings_get_ko_500() {
119        let method = Method::GET.as_str();
120        let path = "/epoch-settings";
121        let mut dependency_manager = initialize_dependencies!().await;
122        let mut mock_http_message_service = MockMessageService::new();
123        mock_http_message_service
124            .expect_get_epoch_settings_message()
125            .return_once(|_| Err(anyhow!("an error")))
126            .once();
127        dependency_manager.message_service = Arc::new(mock_http_message_service);
128
129        let response = request()
130            .method(method)
131            .path(path)
132            .reply(&setup_router(RouterState::new_with_dummy_config(Arc::new(
133                dependency_manager,
134            ))))
135            .await;
136
137        APISpec::verify_conformity(
138            APISpec::get_all_spec_files(),
139            method,
140            path,
141            "application/json",
142            &Null,
143            &response,
144            &StatusCode::INTERNAL_SERVER_ERROR,
145        )
146        .unwrap();
147    }
148}