1use std::sync::Arc;
2
3use http::uri::Authority;
4
5pub use crate::message::stream::{ReadToStringError, StreamError};
6use crate::{
7 connection::{Connection, settings::Settings},
8 pool::{self, Pool},
9 quic,
10};
11
12mod message;
13pub use message::{PendingRequest, Request, RequestError, Response};
14
15#[cfg(feature = "gm-quic")]
16mod gm_quic;
17#[cfg(feature = "gm-quic")]
18pub use crate::{
19 client::gm_quic::{BuildClientError, GmQuicClientBuilder, GmQuicClientTlsBuilder},
20 util::tls::InvalidIdentity,
21};
22
23#[derive(Debug, Clone)]
24pub struct Client<C: quic::Connect> {
25 pool: Pool<C::Connection>,
26 client: C,
27 settings: Arc<Settings>,
28}
29
30#[bon::bon]
31impl<C: quic::Connect> Client<C> {
32 #[builder(
33 builder_type(vis = "pub"),
34 start_fn(name = from_quic_client, vis = "pub")
35 )]
36 fn new(
37 #[builder(default = Pool::global().clone())] pool: Pool<C::Connection>,
38 client: C,
39 #[builder(default)] settings: Arc<Settings>,
40 ) -> Self {
41 Self {
42 pool,
43 client,
44 settings,
45 }
46 }
47
48 pub fn quic_clinet(&self) -> &C {
49 &self.client
50 }
51
52 pub fn quic_client_mut(&mut self) -> &mut C {
53 &mut self.client
54 }
55
56 pub async fn connect(
57 &self,
58 server: Authority,
59 ) -> Result<Arc<Connection<C::Connection>>, pool::ConnectError<C::Error>> {
60 let host_port = server
61 .as_str()
62 .rsplit_once('@')
63 .map(|(_username_password, host_port)| host_port)
64 .unwrap_or(server.as_str());
65 let connect = async || self.client.connect(host_port).await;
66 self.pool
67 .reuse_or_connect_with(server.clone(), self.settings.clone(), connect)
68 .await
69 }
70}
71
72#[cfg(feature = "gm-quic")]
73pub fn builder() -> gm_quic::GmQuicClientTlsBuilder {
74 Client::builder()
75}