ntex_h2/client/
connector.rs

1use std::{marker::PhantomData, ops};
2
3use ntex_bytes::ByteString;
4use ntex_http::uri::Scheme;
5use ntex_io::IoBoxed;
6use ntex_net::connect::{self as connect, Address, Connect, Connector as DefaultConnector};
7use ntex_service::{IntoService, Pipeline, Service};
8use ntex_util::time::timeout_checked;
9
10use crate::{client::ClientError, client::SimpleClient, config::Config};
11
12#[derive(Debug)]
13/// Http2 client connector
14pub struct Connector<A: Address, T> {
15    connector: Pipeline<T>,
16    config: Config,
17    scheme: Scheme,
18
19    _t: PhantomData<A>,
20}
21
22impl<A, T> Connector<A, T>
23where
24    A: Address,
25    T: Service<Connect<A>, Error = connect::ConnectError>,
26    IoBoxed: From<T::Response>,
27{
28    /// Create new http2 connector
29    pub fn new<F>(connector: F) -> Connector<A, T>
30    where
31        F: IntoService<T, Connect<A>>,
32    {
33        Connector {
34            connector: Pipeline::new(connector.into_service()),
35            config: Config::client(),
36            scheme: Scheme::HTTP,
37            _t: PhantomData,
38        }
39    }
40}
41
42impl<A> Default for Connector<A, DefaultConnector<A>>
43where
44    A: Address,
45{
46    /// Create new h2 connector
47    fn default() -> Self {
48        Connector {
49            connector: DefaultConnector::default().into(),
50            config: Config::client(),
51            scheme: Scheme::HTTP,
52            _t: PhantomData,
53        }
54    }
55}
56
57impl<A: Address, T> ops::Deref for Connector<A, T> {
58    type Target = Config;
59
60    fn deref(&self) -> &Self::Target {
61        &self.config
62    }
63}
64
65impl<A: Address, T> ops::DerefMut for Connector<A, T> {
66    fn deref_mut(&mut self) -> &mut Config {
67        &mut self.config
68    }
69}
70
71impl<A, T> Connector<A, T>
72where
73    A: Address,
74{
75    #[inline]
76    /// Set scheme
77    pub fn scheme(&mut self, scheme: Scheme) -> &mut Self {
78        self.scheme = scheme;
79        self
80    }
81
82    /// Use custom connector
83    pub fn connector<U, F>(&self, connector: F) -> Connector<A, U>
84    where
85        F: IntoService<U, Connect<A>>,
86        U: Service<Connect<A>, Error = connect::ConnectError>,
87        IoBoxed: From<U::Response>,
88    {
89        Connector {
90            connector: connector.into_service().into(),
91            config: self.config.clone(),
92            scheme: self.scheme.clone(),
93            _t: PhantomData,
94        }
95    }
96}
97
98impl<A, T> Connector<A, T>
99where
100    A: Address,
101    T: Service<Connect<A>, Error = connect::ConnectError>,
102    IoBoxed: From<T::Response>,
103{
104    /// Connect to http2 server
105    pub async fn connect(&self, address: A) -> Result<SimpleClient, ClientError> {
106        let scheme = self.scheme.clone();
107        let authority = ByteString::from(address.host());
108
109        let fut = async {
110            Ok::<_, ClientError>(SimpleClient::new(
111                self.connector.call(Connect::new(address)).await?,
112                self.config.clone(),
113                scheme,
114                authority,
115            ))
116        };
117
118        timeout_checked(self.config.0.handshake_timeout.get(), fut)
119            .await
120            .map_err(|_| ClientError::HandshakeTimeout)
121            .and_then(|item| item)
122    }
123}