Skip to main content

deboa/client/conn/
pool.rs

1use async_trait::async_trait;
2use std::{collections::HashMap, sync::Arc};
3use url::Url;
4
5#[cfg(feature = "http1")]
6use crate::client::conn::http::Http1Request;
7#[cfg(feature = "http2")]
8use crate::client::conn::http::Http2Request;
9
10use crate::{
11    cert::ClientCert,
12    client::conn::http::{BaseHttpConnection, DeboaConnection, DeboaHttpConnection},
13    HttpVersion, Result,
14};
15
16#[derive(Debug)]
17/// Struct that represents the HTTP connection pool.
18///
19/// # Fields
20///
21/// * `connections` - The connections.
22pub struct HttpConnectionPool {
23    connections: HashMap<String, DeboaConnection>,
24}
25
26impl AsMut<HttpConnectionPool> for HttpConnectionPool {
27    fn as_mut(&mut self) -> &mut HttpConnectionPool {
28        self
29    }
30}
31
32#[async_trait]
33/// Trait that represents the HTTP connection pool.
34pub trait DeboaHttpConnectionPool: private::Sealed {
35    /// Allow create a new connection pool.
36    ///
37    /// # Returns
38    ///
39    /// * `HttpConnectionPool` - The new connection pool.
40    ///
41    fn new() -> Self;
42
43    /// Allow get connections.
44    ///
45    /// # Returns
46    ///
47    /// * `&HashMap<String, DeboaConnection>` - The connections.
48    ///
49    fn connections(&self) -> &HashMap<String, DeboaConnection>;
50
51    /// Allow create a new connection.
52    ///
53    /// # Arguments
54    ///
55    /// * `url` - The url to connect.
56    /// * `protocol` - The protocol to use.
57    /// * `retries` - The number of retries.
58    ///
59    /// # Returns
60    ///
61    /// * `Result<&mut DeboaConnection>` - The connection or error.
62    ///
63    async fn create_connection<'a>(
64        &'a mut self,
65        url: Arc<Url>,
66        protocol: &HttpVersion,
67        client_cert: &Option<ClientCert>,
68    ) -> Result<&'a mut DeboaConnection>;
69}
70
71#[async_trait]
72impl DeboaHttpConnectionPool for HttpConnectionPool {
73    fn new() -> Self {
74        Self { connections: HashMap::new() }
75    }
76
77    #[inline]
78    fn connections(&self) -> &HashMap<String, DeboaConnection> {
79        &self.connections
80    }
81
82    async fn create_connection(
83        &mut self,
84        url: Arc<Url>,
85        protocol: &HttpVersion,
86        client_cert: &Option<ClientCert>,
87    ) -> Result<&mut DeboaConnection> {
88        let mut host = url
89            .host_str()
90            .unwrap()
91            .to_string();
92        if url.port().is_some() {
93            let port = url.port().unwrap();
94            host = format!("{}:{}", host, port);
95        } else {
96            match url.scheme() {
97                "http" | "ws" => host = format!("{}:80", host),
98                "https" | "wss" => host = format!("{}:443", host),
99                _ => panic!("Unsupported scheme: {}", url.scheme()),
100            }
101        }
102
103        let host_key = host;
104        if self
105            .connections
106            .contains_key(&host_key)
107        {
108            return Ok(self
109                .connections
110                .get_mut(&host_key)
111                .unwrap());
112        }
113
114        let connection = match protocol {
115            #[cfg(feature = "http1")]
116            HttpVersion::Http1 => {
117                let connection =
118                    BaseHttpConnection::<Http1Request>::connect(url, client_cert).await?;
119                DeboaConnection::Http1(Box::new(connection))
120            }
121            #[cfg(feature = "http2")]
122            HttpVersion::Http2 => {
123                let connection =
124                    BaseHttpConnection::<Http2Request>::connect(url, client_cert).await?;
125                DeboaConnection::Http2(Box::new(connection))
126            }
127            #[cfg(feature = "http3")]
128            HttpVersion::Http3 => {
129                let connection =
130                    BaseHttpConnection::<Http3Request>::connect(url, client_cert).await?;
131                DeboaConnection::Http3(Box::new(connection))
132            }
133        };
134
135        self.connections
136            .insert(host_key.to_string(), connection);
137        Ok(self
138            .connections
139            .get_mut(&host_key)
140            .unwrap())
141    }
142}
143
144mod private {
145    pub trait Sealed {}
146}
147
148impl private::Sealed for HttpConnectionPool {}