conjure_runtime_rustls_platform_verifier/
raw_client_builder.rs1use conjure_error::Error;
2use conjure_runtime::raw::BuildRawClient;
3use conjure_runtime::{Builder, builder};
4use conjure_runtime_raw::raw::DefaultRawClient;
5use conjure_runtime_raw::raw::{HTTP_KEEPALIVE, TCP_KEEPALIVE};
6use conjure_runtime_raw::service::proxy::ProxyConfig;
7use conjure_runtime_raw::service::proxy::connector::ProxyConnectorLayer;
8use conjure_runtime_raw::service::timeout::TimeoutLayer;
9use conjure_runtime_raw::service::tls_metrics::TlsMetricsLayer;
10use hyper_rustls::HttpsConnectorBuilder;
11use hyper_util::client::legacy::Client;
12use hyper_util::client::legacy::connect::HttpConnector;
13use hyper_util::rt::{TokioExecutor, TokioTimer};
14use rustls::ClientConfig;
15use rustls_platform_verifier::BuilderVerifierExt;
16use tower_layer::Layer;
17
18#[derive(Copy, Clone)]
19pub struct RawClientBuilder;
20
21impl BuildRawClient for RawClientBuilder {
23 type RawClient = DefaultRawClient;
24
25 fn build_raw_client(
26 &self,
27 builder: &Builder<builder::Complete<Self>>,
28 ) -> Result<Self::RawClient, Error> {
29 let mut connector = HttpConnector::new();
30 connector.enforce_http(false);
31 connector.set_nodelay(true);
32 connector.set_keepalive(Some(TCP_KEEPALIVE));
33 connector.set_connect_timeout(Some(builder.get_connect_timeout()));
34
35 let proxy = ProxyConfig::from_config(builder.get_proxy())?;
36
37 let connector = TimeoutLayer::new(builder).layer(connector);
38 let connector = ProxyConnectorLayer::new(&proxy).layer(connector);
39
40 let client_config =
41 ClientConfig::builder_with_provider(crate::crypto::ring_crypto_provider().clone())
42 .with_safe_default_protocol_versions()
43 .map_err(Error::internal_safe)?
44 .with_platform_verifier()
45 .map_err(Error::internal_safe)?;
46
47 let client_config = match (
48 builder.get_security().cert_file(),
49 builder.get_security().key_file(),
50 ) {
51 (Some(cert_file), Some(key_file)) => {
52 let cert_chain = conjure_runtime_raw::raw::load_certs_file(cert_file)?;
53 let private_key = conjure_runtime_raw::raw::load_private_key(key_file)?;
54
55 client_config
56 .with_client_auth_cert(cert_chain, private_key)
57 .map_err(Error::internal_safe)?
58 }
59 (None, None) => client_config.with_no_client_auth(),
60 _ => {
61 return Err(Error::internal_safe(
62 "neither or both of key-file and cert-file must be set in the client \
63 security config",
64 ));
65 }
66 };
67
68 let connector = HttpsConnectorBuilder::new()
69 .with_tls_config(client_config)
70 .https_or_http()
71 .enable_all_versions()
72 .wrap_connector(connector);
73 let connector = TlsMetricsLayer::new(builder).layer(connector);
74
75 let client = Client::builder(TokioExecutor::new())
76 .pool_idle_timeout(HTTP_KEEPALIVE)
77 .pool_timer(TokioTimer::new())
78 .timer(TokioTimer::new())
79 .build(connector);
80
81 Ok(DefaultRawClient(client))
82 }
83}