Skip to main content

io_http/client/
connect.rs

1//! End-to-end connect for the std client, the half that needs a TLS
2//! provider.
3//!
4//! The module is gated once where it is declared, so nothing inside
5//! repeats the feature list.
6
7use alloc::{boxed::Box, string::ToString};
8
9use pimalaya_stream::{
10    stream::{Stream, TcpConnectOptions, TlsConnectOptions},
11    tls::Tls,
12};
13use url::Url;
14
15use crate::client::{HttpClientError, HttpClientStd};
16
17impl HttpClientStd {
18    /// Connects to `url` (TLS handshake on `https`), reading ALPN from
19    /// `tls.rustls.alpn` (see [`Self::default_alpn`]).
20    pub fn connect(url: &Url, tls: &Tls) -> Result<Self, HttpClientError> {
21        let host = url
22            .host_str()
23            .ok_or_else(|| HttpClientError::UrlMissingHost(url.to_string()))?;
24
25        let stream = match url.scheme() {
26            "http" => {
27                let port = url.port_or_known_default().unwrap_or(80);
28                let opts = TcpConnectOptions::default();
29                Stream::connect_tcp(host, port, opts)?
30            }
31            "https" => {
32                let port = url.port_or_known_default().unwrap_or(443);
33                let opts = TlsConnectOptions {
34                    tls: tls.clone(),
35                    ..Default::default()
36                };
37
38                Stream::connect_tls(host, port, opts)?
39            }
40            scheme => {
41                return Err(HttpClientError::UrlUnsupportedScheme(
42                    url.to_string(),
43                    scheme.to_string(),
44                ));
45            }
46        };
47
48        Ok(Self {
49            stream: Box::new(stream),
50        })
51    }
52}