From 04d920016f2a029e7546eaa0fbf0817f9ec02b1d Mon Sep 17 00:00:00 2001 From: Julia Ryan Date: Tue, 9 Dec 2025 09:29:40 -0800 Subject: [PATCH] Remove reqwest dependency from gpui (#44424) This was pulling in tokio which is pretty unfortunate. The solution is to do the `reqwest::Form` to `http::Reqwest` conversion in the reliability crate instead of our http client wrapper. Release Notes: - N/A --- Cargo.lock | 1 - crates/http_client/Cargo.toml | 1 - crates/http_client/src/async_body.rs | 11 -------- crates/http_client/src/http_client.rs | 29 +-------------------- crates/reqwest_client/src/reqwest_client.rs | 20 -------------- crates/zed/src/reliability.rs | 15 ++++++----- 6 files changed, 10 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5790df07111b0752321c9d29da61a16839236275..49b9d6069ccdfadf2d5145808fd7b758f9b389bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7756,7 +7756,6 @@ dependencies = [ "tempfile", "url", "util", - "zed-reqwest", ] [[package]] diff --git a/crates/http_client/Cargo.toml b/crates/http_client/Cargo.toml index 16600627a77f6a73fa913340f29f5a2da0875de9..177f8639ca1a5d75bd0130979f4d550e3622a1b4 100644 --- a/crates/http_client/Cargo.toml +++ b/crates/http_client/Cargo.toml @@ -28,7 +28,6 @@ http-body.workspace = true http.workspace = true log.workspace = true parking_lot.workspace = true -reqwest.workspace = true serde.workspace = true serde_json.workspace = true serde_urlencoded.workspace = true diff --git a/crates/http_client/src/async_body.rs b/crates/http_client/src/async_body.rs index 6b99a54a7d941c290f2680bc2a599bc63251e24b..8fb49f218568ea36078d772a7225229f31a916c4 100644 --- a/crates/http_client/src/async_body.rs +++ b/crates/http_client/src/async_body.rs @@ -88,17 +88,6 @@ impl From<&'static str> for AsyncBody { } } -impl TryFrom for AsyncBody { - type Error = anyhow::Error; - - fn try_from(value: reqwest::Body) -> Result { - value - .as_bytes() - .ok_or_else(|| anyhow::anyhow!("Underlying data is a stream")) - .map(|bytes| Self::from_bytes(Bytes::copy_from_slice(bytes))) - } -} - impl> From> for AsyncBody { fn from(body: Option) -> Self { match body { diff --git a/crates/http_client/src/http_client.rs b/crates/http_client/src/http_client.rs index f357e01da062398d18134df6625d30b8129bf875..1182ef74ca3d59a2d59419e185ff5bd673c5d505 100644 --- a/crates/http_client/src/http_client.rs +++ b/crates/http_client/src/http_client.rs @@ -8,10 +8,7 @@ use derive_more::Deref; use http::HeaderValue; pub use http::{self, Method, Request, Response, StatusCode, Uri, request::Builder}; -use futures::{ - FutureExt as _, - future::{self, BoxFuture}, -}; +use futures::future::BoxFuture; use parking_lot::Mutex; use serde::Serialize; use std::sync::Arc; @@ -110,14 +107,6 @@ pub trait HttpClient: 'static + Send + Sync { fn as_fake(&self) -> &FakeHttpClient { panic!("called as_fake on {}", type_name::()) } - - fn send_multipart_form<'a>( - &'a self, - _url: &str, - _request: reqwest::multipart::Form, - ) -> BoxFuture<'a, anyhow::Result>> { - future::ready(Err(anyhow!("not implemented"))).boxed() - } } /// An [`HttpClient`] that may have a proxy. @@ -165,14 +154,6 @@ impl HttpClient for HttpClientWithProxy { fn as_fake(&self) -> &FakeHttpClient { self.client.as_fake() } - - fn send_multipart_form<'a>( - &'a self, - url: &str, - form: reqwest::multipart::Form, - ) -> BoxFuture<'a, anyhow::Result>> { - self.client.send_multipart_form(url, form) - } } /// An [`HttpClient`] that has a base URL. @@ -306,14 +287,6 @@ impl HttpClient for HttpClientWithUrl { fn as_fake(&self) -> &FakeHttpClient { self.client.as_fake() } - - fn send_multipart_form<'a>( - &'a self, - url: &str, - request: reqwest::multipart::Form, - ) -> BoxFuture<'a, anyhow::Result>> { - self.client.send_multipart_form(url, request) - } } pub fn read_proxy_from_env() -> Option { diff --git a/crates/reqwest_client/src/reqwest_client.rs b/crates/reqwest_client/src/reqwest_client.rs index 4213a239ec813f255139a97770a74608371fb73e..8a1ee45e1cc5364600342d587e6b8c084b5d195a 100644 --- a/crates/reqwest_client/src/reqwest_client.rs +++ b/crates/reqwest_client/src/reqwest_client.rs @@ -270,26 +270,6 @@ impl http_client::HttpClient for ReqwestClient { } .boxed() } - - fn send_multipart_form<'a>( - &'a self, - url: &str, - form: reqwest::multipart::Form, - ) -> futures::future::BoxFuture<'a, anyhow::Result>> - { - let response = self.client.post(url).multipart(form).send(); - self.handle - .spawn(async move { - let response = response.await?; - let mut builder = http::response::Builder::new().status(response.status()); - for (k, v) in response.headers() { - builder = builder.header(k, v) - } - Ok(builder.body(response.bytes().await?.into())?) - }) - .map(|e| e?) - .boxed() - } } #[cfg(test)] diff --git a/crates/zed/src/reliability.rs b/crates/zed/src/reliability.rs index 9d2f7f5da021cda38cef5a205f2d2ec77eb2b386..da8dffa85d57162a62dd6ae0a698d975d22ee374 100644 --- a/crates/zed/src/reliability.rs +++ b/crates/zed/src/reliability.rs @@ -1,8 +1,8 @@ use anyhow::{Context as _, Result}; use client::{Client, telemetry::MINIDUMP_ENDPOINT}; -use futures::AsyncReadExt; +use futures::{AsyncReadExt, TryStreamExt}; use gpui::{App, AppContext as _, SerializedThreadTaskTimings}; -use http_client::{self, HttpClient}; +use http_client::{self, AsyncBody, HttpClient, Request}; use log::info; use project::Project; use proto::{CrashReport, GetCrashFilesResponse}; @@ -296,11 +296,14 @@ async fn upload_minidump( // TODO: feature-flag-context, and more of device-context like screen resolution, available ram, device model, etc + let stream = form + .into_stream() + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) + .into_async_read(); + let body = AsyncBody::from_reader(stream); + let req = Request::builder().uri(endpoint).body(body)?; let mut response_text = String::new(); - let mut response = client - .http_client() - .send_multipart_form(endpoint, form) - .await?; + let mut response = client.http_client().send(req).await?; response .body_mut() .read_to_string(&mut response_text)