1use reqwest::{Client, header, tls::Identity};
2use std::error::Error;
3use std::fs;
4use std::io::Result as IoResult;
5
6pub struct ClientConfig {
7 pub ca_crt: Option<String>,
8 pub client_pem: Option<String>,
9 pub authorisatin: Option<String>
10}
11
12fn file_buf(f: &'_ str) -> IoResult<Vec::<u8>> {
13 let buf = fs::read(f)?;
14 Ok(buf)
15}
16
17
18pub async fn http_client(cfg: ClientConfig) -> Result<Client, Box::<dyn Error>> {
19 let mut client_builder = if let (Some(ca_crt), Some(client_pem)) = (cfg.ca_crt, cfg.client_pem) {
20 let ca_buf = file_buf(&ca_crt)?;
21 let client_buf = file_buf(&client_pem)?;
22 let cert = reqwest::Certificate::from_pem(&ca_buf)?;
23 let identity = Identity::from_pem(&client_buf)?;
24 let client = reqwest::Client::builder().use_rustls_tls();
25 client
26 .tls_built_in_root_certs(false)
27 .add_root_certificate(cert)
28 .identity(identity)
29 .https_only(true)
30 } else {
31 Client::builder()
32 };
33 if let Some(auth) = cfg.authorisatin {
34 let mut headers = header::HeaderMap::new();
35 headers.insert(header::AUTHORIZATION, header::HeaderValue::from_str(&auth)?);
36 client_builder = client_builder.default_headers(headers);
37 }
38 Ok( client_builder.build()? )
39}
40
41
42#[cfg(test)]
43mod tests {
44 use novax_tokio::tokio as tokio;
45
46 #[tokio::test]
47 async fn should_connect_mtls_service() -> Result<(), Box<dyn super::Error>> {
48 let r_client = super::http_client(
49 super::ClientConfig {
50 ca_crt: Some("key/ca.crt".to_string()),
51 client_pem: Some("key/client.pem".to_string()),
52 authorisatin: None
53 }
54 ).await?;
55 let resp = r_client.get("https://localhost:9092/").send().await?;
56 println!("{:?}.... ", resp);
57 Ok(())
58 }
59
60}