Support SSL and Redirects for HTTP Client in Rust

Support SSL and Redirects for HTTP Client in Rust

Rust Dec 8, 2022

In this video, we are going to support SSL for HTTPS URLs and handle Redirects for our HTTP Client which we write earlier in Rust.

If you don't know about how HTTP protocol works you can read This article, and If you didn't watch the Let's write an HTTP Client in Rust series, here you go:

For SSL support I'm using Rustls crate which is written in pure Rust. But as we use tokio runtime, we need to use tokio-rustls crate which is optimized for tokio runtime and we can use it asynchronously.

First, we need to add these crates to cargo.toml file:

tokio-rustls = "0.23.4"
webpki-roots = "0.22.5"

Then add these lines to your new connection function:

let mut root_cert_store = RootCertStore::empty();
        root_cert_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(
   |ta| {
            OwnedTrustAnchor::from_subject_spki_name_constraints(
                .subject,
                ta.spki,
                ta.name_constraints,
            )
        },
    ));
let config = ClientConfig::builder()
    .with_safe_defaults()
    .with_root_certificates(root_cert_store)
    .with_no_client_auth();
let config = TlsConnector::from(Arc::new(config));
let dns_name = ServerName::try_from("**URL**").unwrap();
SSL support for HTTP connection with rustls crate

Basically, we create a list of RootCertStore and add a root from webpki-roots crate to our list. Then create a ClientConfig and the TlsConnector from it which is an essential part of our configs, and dns_name which is another essential part. We have to store config: TlsConnector and dns_name: ServerName variables in a struct and use them in each request we send to the URL.

pub struct Connection {
    pub parsed_url: ParsedUrl,
    pub config: TlsConnector,
    pub dns_name: ServerName
}

the Next part is to create TCPStream and then create a  TlsStream with the variables which we store in the Connection struct.

let mut stream = TcpStream::connect(
    format!("{}:{}", self.parsed_url.host, self.parsed_url.port)
).await?;
let mut stream = self.config.connect(self.dns_name.clone(), stream).await?;

Now we can send requests to any HTTP URL without any problem. for the Redirect part which is project specific, you can watch the Youtube video:

I hope it helps and good luck.

Tags

Benyamin Eskandari

Curious, Experienced Android Developer Also in love with Rust, DevOps, and System Programming Trying to read a lot of books and learn a lot of things, I will write posts about my path on this journey.