Skip to content

Commit 49ef314

Browse files
author
Clément Turmel
committed
feat(client-lib): add a client type with a default value in http headers
1 parent f03f887 commit 49ef314

File tree

2 files changed

+149
-19
lines changed

2 files changed

+149
-19
lines changed

mithril-client/src/client.rs

Lines changed: 146 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::collections::HashMap;
66
use std::sync::Arc;
77

88
use mithril_common::api_version::APIVersionProvider;
9-
use mithril_common::MITHRIL_ORIGIN_TAG_HEADER;
9+
use mithril_common::{MITHRIL_CLIENT_TYPE_HEADER, MITHRIL_ORIGIN_TAG_HEADER};
1010

1111
use crate::aggregator_client::{AggregatorClient, AggregatorHTTPClient};
1212
#[cfg(feature = "unstable")]
@@ -29,6 +29,8 @@ use crate::snapshot_client::SnapshotClient;
2929
use crate::utils::AncillaryVerifier;
3030
use crate::MithrilResult;
3131

32+
const DEFAULT_CLIENT_TYPE: &str = "LIBRARY";
33+
3234
#[cfg(target_family = "wasm")]
3335
const fn one_week_in_seconds() -> u32 {
3436
604800
@@ -151,6 +153,7 @@ pub struct ClientBuilder {
151153
aggregator_endpoint: Option<String>,
152154
genesis_verification_key: String,
153155
origin_tag: Option<String>,
156+
client_type: Option<String>,
154157
#[cfg(feature = "fs")]
155158
ancillary_verification_key: Option<String>,
156159
aggregator_client: Option<Arc<dyn AggregatorClient>>,
@@ -172,6 +175,7 @@ impl ClientBuilder {
172175
aggregator_endpoint: Some(endpoint.to_string()),
173176
genesis_verification_key: genesis_verification_key.to_string(),
174177
origin_tag: None,
178+
client_type: None,
175179
#[cfg(feature = "fs")]
176180
ancillary_verification_key: None,
177181
aggregator_client: None,
@@ -195,6 +199,7 @@ impl ClientBuilder {
195199
aggregator_endpoint: None,
196200
genesis_verification_key: genesis_verification_key.to_string(),
197201
origin_tag: None,
202+
client_type: None,
198203
#[cfg(feature = "fs")]
199204
ancillary_verification_key: None,
200205
aggregator_client: None,
@@ -343,6 +348,14 @@ impl ClientBuilder {
343348
if let Some(origin_tag) = self.origin_tag.clone() {
344349
headers.insert(MITHRIL_ORIGIN_TAG_HEADER.to_string(), origin_tag);
345350
}
351+
if let Some(client_type) = self.client_type.clone() {
352+
headers.insert(MITHRIL_CLIENT_TYPE_HEADER.to_string(), client_type);
353+
} else if !headers.contains_key(MITHRIL_CLIENT_TYPE_HEADER) {
354+
headers.insert(
355+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
356+
DEFAULT_CLIENT_TYPE.to_string(),
357+
);
358+
}
346359

347360
headers
348361
}
@@ -410,11 +423,9 @@ impl ClientBuilder {
410423
self
411424
}
412425

413-
/// Add a [feedback receiver][FeedbackReceiver] to receive [events][crate::feedback::MithrilEvent]
414-
/// for tasks that can have a long duration (ie: snapshot download or a long certificate chain
415-
/// validation).
416-
pub fn add_feedback_receiver(mut self, receiver: Arc<dyn FeedbackReceiver>) -> Self {
417-
self.feedback_receivers.push(receiver);
426+
/// Set the client type.
427+
pub fn with_client_type(mut self, client_type: Option<String>) -> Self {
428+
self.client_type = client_type;
418429
self
419430
}
420431

@@ -423,15 +434,30 @@ impl ClientBuilder {
423434
self.options = options;
424435
self
425436
}
437+
438+
/// Add a [feedback receiver][FeedbackReceiver] to receive [events][crate::feedback::MithrilEvent]
439+
/// for tasks that can have a long duration (ie: snapshot download or a long certificate chain
440+
/// validation).
441+
pub fn add_feedback_receiver(mut self, receiver: Arc<dyn FeedbackReceiver>) -> Self {
442+
self.feedback_receivers.push(receiver);
443+
self
444+
}
426445
}
427446

428447
#[cfg(test)]
429448
mod tests {
430449
use super::*;
431450

451+
fn default_headers() -> HashMap<String, String> {
452+
HashMap::from([(
453+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
454+
DEFAULT_CLIENT_TYPE.to_string(),
455+
)])
456+
}
457+
432458
#[tokio::test]
433459
async fn compute_http_headers_returns_options_http_headers() {
434-
let http_headers = HashMap::from([("Key".to_string(), "Value".to_string())]);
460+
let http_headers = default_headers();
435461
let client_builder = ClientBuilder::new("").with_options(ClientOptions {
436462
http_headers: Some(http_headers.clone()),
437463
});
@@ -443,25 +469,20 @@ mod tests {
443469

444470
#[tokio::test]
445471
async fn compute_http_headers_with_origin_tag_returns_options_http_headers_with_origin_tag() {
446-
let http_headers = HashMap::from([("Key".to_string(), "Value".to_string())]);
472+
let http_headers = default_headers();
447473
let client_builder = ClientBuilder::new("")
448474
.with_options(ClientOptions {
449475
http_headers: Some(http_headers.clone()),
450476
})
451477
.with_origin_tag(Some("CLIENT_TAG".to_string()));
478+
let mut expected_headers = http_headers.clone();
479+
expected_headers.insert(
480+
MITHRIL_ORIGIN_TAG_HEADER.to_string(),
481+
"CLIENT_TAG".to_string(),
482+
);
452483

453484
let computed_headers = client_builder.compute_http_headers();
454-
455-
assert_eq!(
456-
computed_headers,
457-
HashMap::from([
458-
("Key".to_string(), "Value".to_string()),
459-
(
460-
MITHRIL_ORIGIN_TAG_HEADER.to_string(),
461-
"CLIENT_TAG".to_string()
462-
)
463-
])
464-
);
485+
assert_eq!(computed_headers, expected_headers);
465486
}
466487

467488
#[tokio::test]
@@ -495,4 +516,110 @@ mod tests {
495516
assert_eq!(Some(http_headers), builder.options.http_headers);
496517
assert_eq!(None, builder.origin_tag);
497518
}
519+
520+
#[tokio::test]
521+
async fn compute_http_headers_with_client_type_returns_options_http_headers_with_client_type() {
522+
let http_headers = HashMap::from([("Key".to_string(), "Value".to_string())]);
523+
let client_builder = ClientBuilder::new("")
524+
.with_options(ClientOptions {
525+
http_headers: Some(http_headers.clone()),
526+
})
527+
.with_client_type(Some("CLIENT_TYPE".to_string()));
528+
529+
let computed_headers = client_builder.compute_http_headers();
530+
531+
assert_eq!(
532+
computed_headers,
533+
HashMap::from([
534+
("Key".to_string(), "Value".to_string()),
535+
(
536+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
537+
"CLIENT_TYPE".to_string()
538+
)
539+
])
540+
);
541+
}
542+
543+
#[tokio::test]
544+
async fn compute_http_headers_with_options_containing_client_type_returns_client_type() {
545+
let http_headers = HashMap::from([(
546+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
547+
"client type from options".to_string(),
548+
)]);
549+
let client_builder = ClientBuilder::new("").with_options(ClientOptions {
550+
http_headers: Some(http_headers.clone()),
551+
});
552+
553+
let computed_headers = client_builder.compute_http_headers();
554+
555+
assert_eq!(computed_headers, http_headers);
556+
}
557+
558+
#[tokio::test]
559+
async fn test_with_client_type_not_overwrite_other_client_options_attributes() {
560+
let builder = ClientBuilder::new("")
561+
.with_options(ClientOptions { http_headers: None })
562+
.with_client_type(Some("TEST".to_string()));
563+
assert_eq!(None, builder.options.http_headers);
564+
assert_eq!(Some("TEST".to_string()), builder.client_type);
565+
566+
let http_headers = HashMap::from([("Key".to_string(), "Value".to_string())]);
567+
let builder = ClientBuilder::new("")
568+
.with_options(ClientOptions {
569+
http_headers: Some(http_headers.clone()),
570+
})
571+
.with_client_type(Some("TEST".to_string()));
572+
assert_eq!(Some(http_headers), builder.options.http_headers);
573+
assert_eq!(Some("TEST".to_string()), builder.client_type);
574+
}
575+
576+
#[tokio::test]
577+
async fn test_given_a_none_client_type_compute_http_headers_will_set_client_type_to_default_value(
578+
) {
579+
let builder_without_client_type = ClientBuilder::new("");
580+
let computed_headers = builder_without_client_type.compute_http_headers();
581+
582+
assert_eq!(
583+
computed_headers,
584+
HashMap::from([(
585+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
586+
DEFAULT_CLIENT_TYPE.to_string()
587+
)])
588+
);
589+
590+
let builder_with_none_client_type = ClientBuilder::new("").with_client_type(None);
591+
let computed_headers = builder_with_none_client_type.compute_http_headers();
592+
593+
assert_eq!(
594+
computed_headers,
595+
HashMap::from([(
596+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
597+
DEFAULT_CLIENT_TYPE.to_string()
598+
)])
599+
);
600+
}
601+
602+
#[tokio::test]
603+
async fn test_compute_http_headers_will_compute_client_type_header_from_struct_attribute_over_options(
604+
) {
605+
let http_headers = HashMap::from([(
606+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
607+
"client type from options".to_string(),
608+
)]);
609+
let client_builder = ClientBuilder::new("")
610+
.with_options(ClientOptions {
611+
http_headers: Some(http_headers.clone()),
612+
})
613+
.with_client_type(Some("client type".to_string()));
614+
615+
let computed_headers = client_builder.compute_http_headers();
616+
617+
assert_eq!(
618+
computed_headers,
619+
HashMap::from([(
620+
MITHRIL_CLIENT_TYPE_HEADER.to_string(),
621+
"client type".to_string()
622+
)])
623+
);
624+
}
498625
}

mithril-common/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ pub const MITHRIL_AGGREGATOR_VERSION_HEADER: &str = "aggregator-node-version";
7575
/// Mithril origin of the request
7676
pub const MITHRIL_ORIGIN_TAG_HEADER: &str = "mithril-origin-tag";
7777

78+
/// Mithril client type of the request
79+
pub const MITHRIL_CLIENT_TYPE_HEADER: &str = "mithril-client-type";
80+
7881
#[cfg(test)]
7982
mod tests {
8083
#[cfg(feature = "apispec")]

0 commit comments

Comments
 (0)