ic_bn_lib/http/client/
mod.rs1#[cfg(feature = "clients-hyper")]
2pub mod clients_hyper;
3pub mod clients_reqwest;
4
5use std::{fmt, sync::Arc};
6
7use http::HeaderValue;
8use ic_bn_lib_common::traits::http::Client;
9use prometheus::{
10 HistogramVec, IntCounterVec, IntGaugeVec, Registry, register_histogram_vec_with_registry,
11 register_int_counter_vec_with_registry, register_int_gauge_vec_with_registry,
12};
13
14#[derive(Debug, Clone)]
16pub struct ClientStats {
17 pub pool_size: usize,
18 pub outstanding: usize,
19}
20
21pub trait Stats {
23 fn stats(&self) -> ClientStats;
24}
25
26pub trait ClientWithStats: Client + Stats {
28 fn to_client(self: Arc<Self>) -> Arc<dyn Client>;
29}
30
31#[derive(Clone, Debug)]
33struct Metrics {
34 requests: IntCounterVec,
35 requests_inflight: IntGaugeVec,
36 request_duration: HistogramVec,
37}
38
39impl Metrics {
40 pub fn new(registry: &Registry) -> Self {
41 const LABELS: &[&str] = &["host"];
42
43 Self {
44 requests: register_int_counter_vec_with_registry!(
45 format!("http_client_requests_total"),
46 format!("Counts the number of requests"),
47 LABELS,
48 registry
49 )
50 .unwrap(),
51
52 requests_inflight: register_int_gauge_vec_with_registry!(
53 format!("http_client_requests_inflight"),
54 format!("Counts the number of requests that are currently executed"),
55 LABELS,
56 registry
57 )
58 .unwrap(),
59
60 request_duration: register_histogram_vec_with_registry!(
61 format!("http_client_request_duration_sec"),
62 format!("Records the duration of requests in seconds"),
63 LABELS,
64 [0.01, 0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2].to_vec(),
65 registry
66 )
67 .unwrap(),
68 }
69 }
70}
71
72pub fn basic_auth<U, P>(username: U, password: Option<P>) -> HeaderValue
74where
75 U: fmt::Display,
76 P: fmt::Display,
77{
78 use base64::prelude::BASE64_STANDARD;
79 use base64::write::EncoderWriter;
80 use std::io::Write;
81
82 let mut buf = b"Basic ".to_vec();
83 {
84 let mut encoder = EncoderWriter::new(&mut buf, &BASE64_STANDARD);
85 let _ = write!(encoder, "{username}:");
86 if let Some(password) = password {
87 let _ = write!(encoder, "{password}");
88 }
89 }
90
91 let mut header = HeaderValue::from_bytes(&buf).expect("base64 is always valid HeaderValue");
92 header.set_sensitive(true);
93 header
94}