Make following redirects explicit in `HttpClient::get`

Antonio Scandurra created

Change summary

crates/auto_update/src/auto_update.rs    |  3 ++-
crates/client/src/client.rs              |  2 +-
crates/client/src/http.rs                | 24 ++++++++++++++----------
crates/client/src/user.rs                |  2 +-
crates/zed/src/languages/c.rs            |  2 +-
crates/zed/src/languages/installation.rs |  1 +
crates/zed/src/languages/rust.rs         |  2 +-
7 files changed, 21 insertions(+), 15 deletions(-)

Detailed changes

crates/auto_update/src/auto_update.rs 🔗

@@ -137,6 +137,7 @@ impl AutoUpdater {
             .get(
                 &format!("{server_url}/api/releases/latest?token={ACCESS_TOKEN}&asset=Zed.dmg"),
                 Default::default(),
+                true,
             )
             .await?;
 
@@ -173,7 +174,7 @@ impl AutoUpdater {
             .map_or_else(|| cx.platform().app_path(), Ok)?;
 
         let mut dmg_file = File::create(&dmg_path).await?;
-        let mut response = client.get(&release.url, Default::default()).await?;
+        let mut response = client.get(&release.url, Default::default(), true).await?;
         smol::io::copy(response.body_mut(), &mut dmg_file).await?;
         log::info!("downloaded update. path:{:?}", dmg_path);
 

crates/client/src/client.rs 🔗

@@ -781,7 +781,7 @@ impl Client {
         let http = self.http.clone();
         cx.background().spawn(async move {
             let mut rpc_url = format!("{}/rpc", *ZED_SERVER_URL);
-            let rpc_response = http.get(&rpc_url, Default::default()).await?;
+            let rpc_response = http.get(&rpc_url, Default::default(), false).await?;
             if rpc_response.status().is_redirection() {
                 rpc_url = rpc_response
                     .headers()

crates/client/src/http.rs 🔗

@@ -1,15 +1,14 @@
+pub use anyhow::{anyhow, Result};
 use futures::future::BoxFuture;
 use isahc::{
     config::{Configurable, RedirectPolicy},
     AsyncBody,
 };
-use std::sync::Arc;
-
-pub use anyhow::{anyhow, Result};
 pub use isahc::{
     http::{Method, Uri},
     Error,
 };
+use std::sync::Arc;
 pub use url::Url;
 
 pub type Request = isahc::Request<AsyncBody>;
@@ -18,9 +17,19 @@ pub type Response = isahc::Response<AsyncBody>;
 pub trait HttpClient: Send + Sync {
     fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response, Error>>;
 
-    fn get<'a>(&'a self, uri: &str, body: AsyncBody) -> BoxFuture<'a, Result<Response, Error>> {
+    fn get<'a>(
+        &'a self,
+        uri: &str,
+        body: AsyncBody,
+        follow_redirects: bool,
+    ) -> BoxFuture<'a, Result<Response, Error>> {
         self.send(
             isahc::Request::builder()
+                .redirect_policy(if follow_redirects {
+                    RedirectPolicy::Follow
+                } else {
+                    RedirectPolicy::None
+                })
                 .method(Method::GET)
                 .uri(uri)
                 .body(body)
@@ -30,12 +39,7 @@ pub trait HttpClient: Send + Sync {
 }
 
 pub fn client() -> Arc<dyn HttpClient> {
-    Arc::new(
-        isahc::HttpClient::builder()
-            .redirect_policy(RedirectPolicy::Follow)
-            .build()
-            .unwrap(),
-    )
+    Arc::new(isahc::HttpClient::builder().build().unwrap())
 }
 
 impl HttpClient for isahc::HttpClient {

crates/client/src/user.rs 🔗

@@ -253,7 +253,7 @@ impl Contact {
 
 async fn fetch_avatar(http: &dyn HttpClient, url: &str) -> Result<Arc<ImageData>> {
     let mut response = http
-        .get(url, Default::default())
+        .get(url, Default::default(), true)
         .await
         .map_err(|e| anyhow!("failed to send user avatar request: {}", e))?;
 

crates/zed/src/languages/c.rs 🔗

@@ -42,7 +42,7 @@ impl super::LspAdapter for CLspAdapter {
 
             if fs::metadata(&binary_path).await.is_err() {
                 let mut response = http
-                    .get(&version.url, Default::default())
+                    .get(&version.url, Default::default(), true)
                     .await
                     .context("error downloading release")?;
                 let mut file = File::create(&zip_path).await?;

crates/zed/src/languages/installation.rs 🔗

@@ -87,6 +87,7 @@ pub async fn latest_github_release(
         .get(
             &format!("https://api.github.com/repos/{repo_name_with_owner}/releases/latest"),
             Default::default(),
+            true,
         )
         .await
         .context("error fetching latest release")?;

crates/zed/src/languages/rust.rs 🔗

@@ -43,7 +43,7 @@ impl LspAdapter for RustLspAdapter {
 
             if fs::metadata(&destination_path).await.is_err() {
                 let mut response = http
-                    .get(&version.url, Default::default())
+                    .get(&version.url, Default::default(), true)
                     .await
                     .map_err(|err| anyhow!("error downloading release: {}", err))?;
                 let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));