mithril_aggregator_client/query/post/
post_register_signature.rs1use async_trait::async_trait;
2use reqwest::StatusCode;
3use slog::debug;
4
5use mithril_common::messages::RegisterSignatureMessageHttp;
6
7use crate::query::{AggregatorQuery, QueryContext, QueryLogFields, QueryMethod};
8use crate::{AggregatorHttpClientError, AggregatorHttpClientResult};
9
10pub struct PostRegisterSignatureQuery {
12 message: RegisterSignatureMessageHttp,
13}
14
15impl PostRegisterSignatureQuery {
16 pub fn new(message: RegisterSignatureMessageHttp) -> Self {
18 Self { message }
19 }
20}
21
22#[cfg_attr(target_family = "wasm", async_trait(?Send))]
23#[cfg_attr(not(target_family = "wasm"), async_trait)]
24impl AggregatorQuery for PostRegisterSignatureQuery {
25 type Response = ();
26 type Body = RegisterSignatureMessageHttp;
27
28 fn method() -> QueryMethod {
29 QueryMethod::Post
30 }
31
32 fn route(&self) -> String {
33 "register-signatures".to_string()
34 }
35
36 fn body(&self) -> Option<Self::Body> {
37 Some(self.message.clone())
38 }
39
40 fn entry_log_additional_fields(&self) -> QueryLogFields {
41 QueryLogFields::from([
42 ("party_id", self.message.party_id.clone()),
43 (
44 "signed_entity",
45 format!("{:?}", self.message.signed_entity_type),
46 ),
47 ])
48 }
49
50 async fn handle_response(
51 &self,
52 context: QueryContext,
53 ) -> AggregatorHttpClientResult<Self::Response> {
54 match context.response.status() {
55 StatusCode::CREATED | StatusCode::ACCEPTED => Ok(()),
56 StatusCode::GONE => {
57 let root_cause = AggregatorHttpClientError::get_root_cause(context.response).await;
58 debug!(context.logger, "Message already certified or expired"; "details" => &root_cause);
59
60 Ok(())
61 }
62 _ => Err(context.unhandled_status_code().await),
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use httpmock::Method::POST;
70
71 use mithril_common::entities::ClientError;
72 use mithril_common::test::double::Dummy;
73
74 use crate::test::{TestLogger, assert_error_matches, setup_server_and_client};
75
76 use super::*;
77
78 #[tokio::test]
79 async fn test_register_signature_ok_201() {
80 let expected_message = RegisterSignatureMessageHttp::dummy();
81 let (server, client) = setup_server_and_client();
82 let _server_mock = server.mock(|when, then| {
83 when.method(POST)
84 .path("/register-signatures")
85 .body(serde_json::to_string(&expected_message).unwrap());
86 then.status(201);
87 });
88
89 let register_signature =
90 client.send(PostRegisterSignatureQuery::new(expected_message)).await;
91 register_signature.expect("unexpected error");
92 }
93
94 #[tokio::test]
95 async fn test_register_signature_ok_202() {
96 let (server, client) = setup_server_and_client();
97 let _server_mock = server.mock(|when, then| {
98 when.method(POST).path("/register-signatures");
99 then.status(202);
100 });
101
102 let register_signature = client
103 .send(PostRegisterSignatureQuery::new(
104 RegisterSignatureMessageHttp::dummy(),
105 ))
106 .await;
107 register_signature.expect("unexpected error");
108 }
109
110 #[tokio::test]
111 async fn test_register_signature_ko_400() {
112 let (server, client) = setup_server_and_client();
113 let _server_mock = server.mock(|when, then| {
114 when.any_request();
115 then.status(400)
116 .body(serde_json::to_vec(&ClientError::dummy()).unwrap());
117 });
118
119 let error = client
120 .send(PostRegisterSignatureQuery::new(
121 RegisterSignatureMessageHttp::dummy(),
122 ))
123 .await
124 .unwrap_err();
125
126 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerLogical(_));
127 }
128
129 #[tokio::test]
130 async fn test_register_signature_ok_410_log_response_body() {
131 let (logger, log_inspector) = TestLogger::memory();
132
133 let (server, mut client) = setup_server_and_client();
134 client.logger = logger;
135 let _server_mock = server.mock(|when, then| {
136 when.any_request();
137 then.status(410).body(
138 serde_json::to_vec(&ClientError::new(
139 "already_aggregated".to_string(),
140 "too late".to_string(),
141 ))
142 .unwrap(),
143 );
144 });
145
146 client
147 .send(PostRegisterSignatureQuery::new(
148 RegisterSignatureMessageHttp::dummy(),
149 ))
150 .await
151 .expect("Should not fail when status is 410 (GONE)");
152
153 assert!(log_inspector.contains_log("already_aggregated"));
154 assert!(log_inspector.contains_log("too late"));
155 }
156
157 #[tokio::test]
158 async fn test_register_signature_ko_409() {
159 let (server, client) = setup_server_and_client();
160 let _server_mock = server.mock(|when, then| {
161 when.any_request();
162 then.status(409);
163 });
164
165 let error = client
166 .send(PostRegisterSignatureQuery::new(
167 RegisterSignatureMessageHttp::dummy(),
168 ))
169 .await
170 .unwrap_err();
171
172 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerLogical(_));
173 }
174
175 #[tokio::test]
176 async fn test_register_signature_ko_500() {
177 let (server, client) = setup_server_and_client();
178 let _server_mock = server.mock(|when, then| {
179 when.any_request();
180 then.status(500).body("an error occurred");
181 });
182
183 let error = client
184 .send(PostRegisterSignatureQuery::new(
185 RegisterSignatureMessageHttp::dummy(),
186 ))
187 .await
188 .unwrap_err();
189
190 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
191 }
192}