|
9 | 9 | use std::collections::{hash_map, HashMap, VecDeque}; |
10 | 10 | use std::sync::{Arc, Mutex}; |
11 | 11 |
|
| 12 | +#[cfg(any( |
| 13 | + all(feature = "native-tls", feature = "tokio-native-tls"), |
| 14 | + all(feature = "rustls", feature = "tokio-rustls") |
| 15 | +))] |
| 16 | +use crate::connection::certificates::Certificates; |
12 | 17 | use crate::connection::AsyncConnection; |
13 | 18 | use crate::request::{OwnedConnectionParams as ConnectionKey, ParsedRequest}; |
14 | 19 | use crate::{Error, Request, Response}; |
15 | 20 |
|
16 | | -mod tls { |
17 | | - #[cfg(not(any( |
18 | | - all(feature = "native-tls", feature = "tokio-native-tls"), |
19 | | - all(feature = "rustls", feature = "tokio-rustls") |
20 | | - )))] |
21 | | - pub(crate) use self::disabled::*; |
| 21 | +#[derive(Clone)] |
| 22 | +pub(crate) struct ClientConfig { |
22 | 23 | #[cfg(any( |
23 | 24 | all(feature = "native-tls", feature = "tokio-native-tls"), |
24 | 25 | all(feature = "rustls", feature = "tokio-rustls") |
25 | 26 | ))] |
26 | | - pub(crate) use self::enabled::*; |
| 27 | + pub(crate) tls: Option<TlsConfig>, |
| 28 | +} |
27 | 29 |
|
28 | | - #[cfg(not(any( |
| 30 | +impl ClientConfig { |
| 31 | + #[cfg(any( |
29 | 32 | all(feature = "native-tls", feature = "tokio-native-tls"), |
30 | 33 | all(feature = "rustls", feature = "tokio-rustls") |
31 | | - )))] |
32 | | - mod disabled { |
33 | | - use crate::Error; |
34 | | - |
35 | | - #[derive(Clone)] |
36 | | - pub(crate) struct ClientConfig; |
37 | | - |
38 | | - impl ClientConfig { |
39 | | - pub fn build(self) -> Result<Self, Error> { Ok(Self) } |
40 | | - } |
| 34 | + ))] |
| 35 | + pub fn build(self) -> Result<Self, Error> { |
| 36 | + let tls = self.tls.map(|tls| tls.build()).transpose()?; |
| 37 | + Ok(Self { tls }) |
41 | 38 | } |
42 | 39 |
|
43 | | - #[cfg(any( |
| 40 | + #[cfg(not(any( |
44 | 41 | all(feature = "native-tls", feature = "tokio-native-tls"), |
45 | 42 | all(feature = "rustls", feature = "tokio-rustls") |
46 | | - ))] |
47 | | - mod enabled { |
48 | | - use crate::client::ClientBuilder; |
49 | | - use crate::connection::certificates::Certificates; |
50 | | - use crate::Error; |
51 | | - |
52 | | - #[derive(Clone)] |
53 | | - pub(crate) struct ClientConfig { |
54 | | - pub(crate) tls: Option<TlsConfig>, |
55 | | - } |
56 | | - |
57 | | - impl ClientConfig { |
58 | | - pub fn build(self) -> Result<Self, Error> { |
59 | | - let tls = self.tls.map(|tls| tls.build()).transpose()?; |
60 | | - Ok(Self { tls }) |
61 | | - } |
62 | | - } |
63 | | - |
64 | | - #[derive(Clone)] |
65 | | - pub(crate) struct TlsConfig { |
66 | | - pub(crate) certificates: Certificates, |
67 | | - } |
68 | | - |
69 | | - impl TlsConfig { |
70 | | - fn new(cert_der: Vec<u8>) -> Result<Self, Error> { |
71 | | - let certificates = Certificates::new(Some(cert_der))?; |
| 43 | + )))] |
| 44 | + pub fn build(self) -> Result<Self, Error> { Ok(Self {}) } |
| 45 | +} |
72 | 46 |
|
73 | | - Ok(Self { certificates }) |
74 | | - } |
| 47 | +#[cfg(any( |
| 48 | + all(feature = "native-tls", feature = "tokio-native-tls"), |
| 49 | + all(feature = "rustls", feature = "tokio-rustls") |
| 50 | +))] |
| 51 | +#[derive(Clone)] |
| 52 | +pub(crate) struct TlsConfig { |
| 53 | + pub(crate) certificates: Certificates, |
| 54 | +} |
75 | 55 |
|
76 | | - #[cfg(all(feature = "rustls", feature = "tokio-rustls"))] |
77 | | - fn build(mut self) -> Result<Self, Error> { |
78 | | - self.certificates = self.certificates.with_root_certificates(); |
79 | | - Ok(self) |
80 | | - } |
| 56 | +#[cfg(any( |
| 57 | + all(feature = "native-tls", feature = "tokio-native-tls"), |
| 58 | + all(feature = "rustls", feature = "tokio-rustls") |
| 59 | +))] |
| 60 | +impl TlsConfig { |
| 61 | + fn new(cert_der: Vec<u8>) -> Result<Self, Error> { |
| 62 | + let certificates = Certificates::new(Some(cert_der))?; |
81 | 63 |
|
82 | | - #[cfg(all( |
83 | | - feature = "native-tls", |
84 | | - not(feature = "rustls"), |
85 | | - feature = "tokio-native-tls" |
86 | | - ))] |
87 | | - fn build(mut self) -> Result<Self, Error> { |
88 | | - let certificates = self.certificates.build()?; |
| 64 | + Ok(Self { certificates }) |
| 65 | + } |
89 | 66 |
|
90 | | - self.certificates = certificates; |
91 | | - Ok(self) |
92 | | - } |
93 | | - } |
| 67 | + #[cfg(all(feature = "rustls", feature = "tokio-rustls"))] |
| 68 | + fn build(mut self) -> Result<Self, Error> { |
| 69 | + self.certificates = self.certificates.with_root_certificates(); |
| 70 | + Ok(self) |
| 71 | + } |
94 | 72 |
|
95 | | - impl ClientBuilder { |
96 | | - /// Adds a custom root certificate for TLS verification. |
97 | | - /// |
98 | | - /// The certificate must be provided in DER format. This method accepts any type |
99 | | - /// that can be converted into a `Vec<u8>`, such as `Vec<u8>`, `&[u8]`, or arrays. |
100 | | - /// This is useful when connecting to servers using self-signed certificates |
101 | | - /// or custom Certificate Authorities. |
102 | | - /// |
103 | | - /// # Arguments |
104 | | - /// |
105 | | - /// * `cert_der` - A DER-encoded X.509 certificate. Accepts any type that implements |
106 | | - /// `Into<Vec<u8>>` (e.g., `&[u8]`, `Vec<u8>`, or `[u8; N]`). |
107 | | - /// |
108 | | - /// # Example |
109 | | - /// |
110 | | - /// ```no_run |
111 | | - /// # use bitreq::Client; |
112 | | - /// # async fn example() -> Result<(), bitreq::Error> { |
113 | | - /// // Using a byte slice |
114 | | - /// let cert_der: &[u8] = include_bytes!("../tests/test_cert.der"); |
115 | | - /// let client = Client::builder() |
116 | | - /// .with_root_certificate(cert_der) |
117 | | - /// .unwrap() |
118 | | - /// .build()?; |
119 | | - /// |
120 | | - /// // Using a Vec<u8> |
121 | | - /// let cert_vec: Vec<u8> = cert_der.to_vec(); |
122 | | - /// let client = Client::builder() |
123 | | - /// .with_root_certificate(cert_vec) |
124 | | - /// .unwrap() |
125 | | - /// .build()?; |
126 | | - /// # Ok(()) |
127 | | - /// # } |
128 | | - /// ``` |
129 | | - pub fn with_root_certificate<T: Into<Vec<u8>>>( |
130 | | - mut self, |
131 | | - cert_der: T, |
132 | | - ) -> Result<Self, Error> { |
133 | | - let cert_der = cert_der.into(); |
134 | | - |
135 | | - if let Some(ref mut client_config) = self.client_config { |
136 | | - if let Some(ref mut tls_config) = client_config.tls { |
137 | | - let certificates = |
138 | | - tls_config.certificates.clone().append_certificate(cert_der)?; |
139 | | - tls_config.certificates = certificates; |
140 | | - |
141 | | - return Ok(self); |
142 | | - } |
143 | | - } |
| 73 | + #[cfg(all(feature = "native-tls", not(feature = "rustls"), feature = "tokio-native-tls"))] |
| 74 | + fn build(mut self) -> Result<Self, Error> { |
| 75 | + let certificates = self.certificates.build()?; |
144 | 76 |
|
145 | | - let tls_config = TlsConfig::new(cert_der)?; |
146 | | - self.client_config = Some(ClientConfig { tls: Some(tls_config) }); |
147 | | - Ok(self) |
148 | | - } |
149 | | - } |
| 77 | + self.certificates = certificates; |
| 78 | + Ok(self) |
150 | 79 | } |
151 | 80 | } |
152 | 81 |
|
153 | | -pub(crate) use tls::ClientConfig; |
154 | | - |
155 | 82 | pub struct ClientBuilder { |
156 | 83 | capacity: usize, |
157 | 84 | client_config: Option<ClientConfig>, |
@@ -231,6 +158,60 @@ impl ClientBuilder { |
231 | 158 | })), |
232 | 159 | }) |
233 | 160 | } |
| 161 | + |
| 162 | + /// Adds a custom root certificate for TLS verification. |
| 163 | + /// |
| 164 | + /// The certificate must be provided in DER format. This method accepts any type |
| 165 | + /// that can be converted into a `Vec<u8>`, such as `Vec<u8>`, `&[u8]`, or arrays. |
| 166 | + /// This is useful when connecting to servers using self-signed certificates |
| 167 | + /// or custom Certificate Authorities. |
| 168 | + /// |
| 169 | + /// # Arguments |
| 170 | + /// |
| 171 | + /// * `cert_der` - A DER-encoded X.509 certificate. Accepts any type that implements |
| 172 | + /// `Into<Vec<u8>>` (e.g., `&[u8]`, `Vec<u8>`, or `[u8; N]`). |
| 173 | + /// |
| 174 | + /// # Example |
| 175 | + /// |
| 176 | + /// ```no_run |
| 177 | + /// # use bitreq::Client; |
| 178 | + /// # async fn example() -> Result<(), bitreq::Error> { |
| 179 | + /// // Using a byte slice |
| 180 | + /// let cert_der: &[u8] = include_bytes!("../tests/test_cert.der"); |
| 181 | + /// let client = Client::builder() |
| 182 | + /// .with_root_certificate(cert_der) |
| 183 | + /// .unwrap() |
| 184 | + /// .build()?; |
| 185 | + /// |
| 186 | + /// // Using a Vec<u8> |
| 187 | + /// let cert_vec: Vec<u8> = cert_der.to_vec(); |
| 188 | + /// let client = Client::builder() |
| 189 | + /// .with_root_certificate(cert_vec) |
| 190 | + /// .unwrap() |
| 191 | + /// .build()?; |
| 192 | + /// # Ok(()) |
| 193 | + /// # } |
| 194 | + /// ``` |
| 195 | + #[cfg(any( |
| 196 | + all(feature = "native-tls", feature = "tokio-native-tls"), |
| 197 | + all(feature = "rustls", feature = "tokio-rustls") |
| 198 | + ))] |
| 199 | + pub fn with_root_certificate<T: Into<Vec<u8>>>(mut self, cert_der: T) -> Result<Self, Error> { |
| 200 | + let cert_der = cert_der.into(); |
| 201 | + |
| 202 | + if let Some(ref mut client_config) = self.client_config { |
| 203 | + if let Some(ref mut tls_config) = client_config.tls { |
| 204 | + let certificates = tls_config.certificates.clone().append_certificate(cert_der)?; |
| 205 | + tls_config.certificates = certificates; |
| 206 | + |
| 207 | + return Ok(self); |
| 208 | + } |
| 209 | + } |
| 210 | + |
| 211 | + let tls_config = TlsConfig::new(cert_der)?; |
| 212 | + self.client_config = Some(ClientConfig { tls: Some(tls_config) }); |
| 213 | + Ok(self) |
| 214 | + } |
234 | 215 | } |
235 | 216 |
|
236 | 217 | impl Default for ClientBuilder { |
|
0 commit comments