deboa/client/conn/
pool.rs1use 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)]
17pub 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]
33pub trait DeboaHttpConnectionPool: private::Sealed {
35 fn new() -> Self;
42
43 fn connections(&self) -> &HashMap<String, DeboaConnection>;
50
51 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 {}