chore: Extract http-client-tls crate (#26895)

Piotr Osiewicz created

http-client pulled in rustls which in turn meant that gpui depended on
rustls/aws-lc-sys. This commit extracts http-client-tls crate to
separate the http-client and tls dependencies.

Closes #ISSUE

Release Notes:

- N/A

Change summary

Cargo.lock                                    | 12 ++++++++++--
Cargo.toml                                    |  2 ++
crates/client/Cargo.toml                      |  1 +
crates/client/src/client.rs                   |  2 +-
crates/http_client/Cargo.toml                 |  2 --
crates/http_client/src/http_client.rs         | 21 +--------------------
crates/http_client_tls/Cargo.toml             | 20 ++++++++++++++++++++
crates/http_client_tls/LICENSE-APACHE         |  1 +
crates/http_client_tls/src/http_client_tls.rs | 21 +++++++++++++++++++++
crates/reqwest_client/Cargo.toml              |  1 +
crates/reqwest_client/src/reqwest_client.rs   |  2 +-
11 files changed, 59 insertions(+), 26 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2739,6 +2739,7 @@ dependencies = [
  "futures 0.3.31",
  "gpui",
  "http_client",
+ "http_client_tls",
  "log",
  "parking_lot",
  "paths",
@@ -6201,13 +6202,19 @@ dependencies = [
  "futures 0.3.31",
  "http 1.2.0",
  "log",
- "rustls 0.23.23",
- "rustls-platform-verifier",
  "serde",
  "serde_json",
  "url",
 ]
 
+[[package]]
+name = "http_client_tls"
+version = "0.1.0"
+dependencies = [
+ "rustls 0.23.23",
+ "rustls-platform-verifier",
+]
+
 [[package]]
 name = "httparse"
 version = "1.9.5"
@@ -11460,6 +11467,7 @@ dependencies = [
  "futures 0.3.31",
  "gpui",
  "http_client",
+ "http_client_tls",
  "log",
  "regex",
  "reqwest 0.12.8",

Cargo.toml 🔗

@@ -65,6 +65,7 @@ members = [
     "crates/gpui_tokio",
     "crates/html_to_markdown",
     "crates/http_client",
+    "crates/http_client_tls",
     "crates/image_viewer",
     "crates/indexed_docs",
     "crates/inline_completion",
@@ -262,6 +263,7 @@ gpui_macros = { path = "crates/gpui_macros" }
 gpui_tokio = { path = "crates/gpui_tokio" }
 html_to_markdown = { path = "crates/html_to_markdown" }
 http_client = { path = "crates/http_client" }
+http_client_tls = { path = "crates/http_client_tls" }
 image_viewer = { path = "crates/image_viewer" }
 indexed_docs = { path = "crates/indexed_docs" }
 inline_completion = { path = "crates/inline_completion" }

crates/client/Cargo.toml 🔗

@@ -27,6 +27,7 @@ feature_flags.workspace = true
 futures.workspace = true
 gpui.workspace = true
 http_client.workspace = true
+http_client_tls.workspace = true
 log.workspace = true
 paths.workspace = true
 parking_lot.workspace = true

crates/client/src/client.rs 🔗

@@ -1154,7 +1154,7 @@ impl Client {
                         async_tungstenite::async_tls::client_async_tls_with_connector(
                             request,
                             stream,
-                            Some(http_client::tls_config().into()),
+                            Some(http_client_tls::tls_config().into()),
                         )
                         .await?;
                     Ok(Connection::new(

crates/http_client/Cargo.toml 🔗

@@ -25,5 +25,3 @@ log.workspace = true
 serde.workspace = true
 serde_json.workspace = true
 url.workspace = true
-rustls.workspace = true
-rustls-platform-verifier.workspace = true

crates/http_client/src/http_client.rs 🔗

@@ -8,33 +8,14 @@ pub use http::{self, Method, Request, Response, StatusCode, Uri};
 
 use futures::future::BoxFuture;
 use http::request::Builder;
-use rustls::ClientConfig;
-use rustls_platform_verifier::ConfigVerifierExt;
 #[cfg(feature = "test-support")]
 use std::fmt;
 use std::{
     any::type_name,
-    sync::{Arc, Mutex, OnceLock},
+    sync::{Arc, Mutex},
 };
 pub use url::Url;
 
-static TLS_CONFIG: OnceLock<rustls::ClientConfig> = OnceLock::new();
-
-pub fn tls_config() -> ClientConfig {
-    TLS_CONFIG
-        .get_or_init(|| {
-            // rustls uses the `aws_lc_rs` provider by default
-            // This only errors if the default provider has already
-            // been installed. We can ignore this `Result`.
-            rustls::crypto::aws_lc_rs::default_provider()
-                .install_default()
-                .ok();
-
-            ClientConfig::with_platform_verifier()
-        })
-        .clone()
-}
-
 #[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
 pub enum RedirectPolicy {
     #[default]

crates/http_client_tls/Cargo.toml 🔗

@@ -0,0 +1,20 @@
+[package]
+name = "http_client_tls"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "Apache-2.0"
+
+[lints]
+workspace = true
+
+[features]
+test-support = []
+
+[lib]
+path = "src/http_client_tls.rs"
+doctest = true
+
+[dependencies]
+rustls.workspace = true
+rustls-platform-verifier.workspace = true

crates/http_client_tls/src/http_client_tls.rs 🔗

@@ -0,0 +1,21 @@
+use std::sync::OnceLock;
+
+use rustls::ClientConfig;
+use rustls_platform_verifier::ConfigVerifierExt;
+
+static TLS_CONFIG: OnceLock<rustls::ClientConfig> = OnceLock::new();
+
+pub fn tls_config() -> ClientConfig {
+    TLS_CONFIG
+        .get_or_init(|| {
+            // rustls uses the `aws_lc_rs` provider by default
+            // This only errors if the default provider has already
+            // been installed. We can ignore this `Result`.
+            rustls::crypto::aws_lc_rs::default_provider()
+                .install_default()
+                .ok();
+
+            ClientConfig::with_platform_verifier()
+        })
+        .clone()
+}

crates/reqwest_client/Cargo.toml 🔗

@@ -24,6 +24,7 @@ anyhow.workspace = true
 bytes.workspace = true
 futures.workspace = true
 http_client.workspace = true
+http_client_tls.workspace = true
 serde.workspace = true
 smol.workspace = true
 log.workspace = true

crates/reqwest_client/src/reqwest_client.rs 🔗

@@ -56,7 +56,7 @@ impl ReqwestClient {
         }
 
         let client = client
-            .use_preconfigured_tls(http_client::tls_config())
+            .use_preconfigured_tls(http_client_tls::tls_config())
             .build()?;
         let mut client: ReqwestClient = client.into();
         client.proxy = proxy;