Remove async-std and surf from client

Nathan Sobo created

Switch to isahc library. It's not as fancy, but it works and has a smaller footprint.

Change summary

Cargo.lock                               | 399 ++-----------------------
crates/auto_update/Cargo.toml            |   2 
crates/auto_update/src/auto_update.rs    |  36 +-
crates/client/Cargo.toml                 |   3 
crates/client/src/channel.rs             |   3 
crates/client/src/client.rs              |  23 
crates/client/src/http.rs                |  47 ++
crates/client/src/test.rs                |  21 
crates/client/src/user.rs                |  27 
crates/workspace/src/workspace.rs        |   4 
crates/zed/Cargo.toml                    |   2 
crates/zed/src/languages/c.rs            |  16 
crates/zed/src/languages/installation.rs |  36 +-
crates/zed/src/languages/rust.rs         |  14 
14 files changed, 160 insertions(+), 473 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -23,60 +23,6 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
 
-[[package]]
-name = "aead"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "aes"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
-dependencies = [
- "aes-soft",
- "aesni",
- "cipher 0.2.5",
-]
-
-[[package]]
-name = "aes-gcm"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
-dependencies = [
- "aead",
- "aes",
- "cipher 0.2.5",
- "ctr",
- "ghash",
- "subtle",
-]
-
-[[package]]
-name = "aes-soft"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug",
-]
-
-[[package]]
-name = "aesni"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug",
-]
-
 [[package]]
 name = "ahash"
 version = "0.7.4"
@@ -205,22 +151,6 @@ dependencies = [
  "futures-lite",
 ]
 
-[[package]]
-name = "async-global-executor"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6"
-dependencies = [
- "async-channel",
- "async-executor",
- "async-io",
- "async-mutex",
- "blocking",
- "futures-lite",
- "num_cpus",
- "once_cell",
-]
-
 [[package]]
 name = "async-io"
 version = "1.3.1"
@@ -250,15 +180,6 @@ dependencies = [
  "event-listener",
 ]
 
-[[package]]
-name = "async-mutex"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
-dependencies = [
- "event-listener",
-]
-
 [[package]]
 name = "async-net"
 version = "1.5.0"
@@ -307,33 +228,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "async-std"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341"
-dependencies = [
- "async-channel",
- "async-global-executor",
- "async-io",
- "async-lock",
- "crossbeam-utils 0.8.2",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-lite",
- "gloo-timers",
- "kv-log-macro",
- "log",
- "memchr",
- "num_cpus",
- "once_cell",
- "pin-project-lite 0.2.8",
- "pin-utils",
- "slab",
- "wasm-bindgen-futures",
-]
-
 [[package]]
 name = "async-task"
 version = "4.0.3"
@@ -419,13 +313,13 @@ dependencies = [
  "anyhow",
  "client",
  "gpui",
+ "isahc",
  "lazy_static",
  "log",
  "serde",
  "serde_json",
  "settings",
  "smol",
- "surf",
  "tempdir",
  "theme",
  "workspace",
@@ -453,7 +347,7 @@ dependencies = [
  "axum-core",
  "base64 0.13.0",
  "bitflags",
- "bytes 1.0.1",
+ "bytes",
  "futures-util",
  "headers",
  "http",
@@ -485,7 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3ddbd16eabff8b45f21b98671fddcc93daaa7ac4c84f8473693437226040de5"
 dependencies = [
  "async-trait",
- "bytes 1.0.1",
+ "bytes",
  "futures-util",
  "http",
  "http-body",
@@ -667,12 +561,6 @@ version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
 
-[[package]]
-name = "bytes"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
-
 [[package]]
 name = "bytes"
 version = "1.0.1"
@@ -685,6 +573,12 @@ version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
 
+[[package]]
+name = "castaway"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6"
+
 [[package]]
 name = "cc"
 version = "1.0.67"
@@ -749,15 +643,6 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
 
-[[package]]
-name = "cipher"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
-dependencies = [
- "generic-array",
-]
-
 [[package]]
 name = "cipher"
 version = "0.3.0"
@@ -847,6 +732,7 @@ dependencies = [
  "futures",
  "gpui",
  "image",
+ "isahc",
  "lazy_static",
  "log",
  "parking_lot",
@@ -855,10 +741,10 @@ dependencies = [
  "rpc",
  "smol",
  "sum_tree",
- "surf",
  "thiserror",
  "time 0.3.7",
  "tiny_http",
+ "url",
  "util",
 ]
 
@@ -1007,23 +893,6 @@ dependencies = [
  "workspace",
 ]
 
-[[package]]
-name = "cookie"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
-dependencies = [
- "aes-gcm",
- "base64 0.13.0",
- "hkdf",
- "hmac 0.10.1",
- "percent-encoding",
- "rand 0.8.3",
- "sha2 0.9.5",
- "time 0.2.27",
- "version_check",
-]
-
 [[package]]
 name = "core-foundation"
 version = "0.9.1"
@@ -1100,12 +969,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "cpuid-bool"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
-
 [[package]]
 name = "crc"
 version = "1.8.1"
@@ -1242,15 +1105,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "ctr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
-dependencies = [
- "cipher 0.2.5",
-]
-
 [[package]]
 name = "curl"
 version = "0.4.42"
@@ -1282,22 +1136,6 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
-[[package]]
-name = "dashmap"
-version = "4.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
-dependencies = [
- "cfg-if 1.0.0",
- "num_cpus",
-]
-
-[[package]]
-name = "data-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
-
 [[package]]
 name = "data-url"
 version = "0.1.0"
@@ -1645,17 +1483,6 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e"
 
-[[package]]
-name = "flume"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bebadab126f8120d410b677ed95eee4ba6eb7c6dd8e34a5ec88a08050e26132"
-dependencies = [
- "futures-core",
- "futures-sink",
- "spinning_top",
-]
-
 [[package]]
 name = "fnv"
 version = "1.0.7"
@@ -1947,16 +1774,6 @@ dependencies = [
  "wasi 0.10.0+wasi-snapshot-preview1",
 ]
 
-[[package]]
-name = "ghash"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
-dependencies = [
- "opaque-debug",
- "polyval",
-]
-
 [[package]]
 name = "gif"
 version = "0.11.2"
@@ -1992,19 +1809,6 @@ dependencies = [
  "regex",
 ]
 
-[[package]]
-name = "gloo-timers"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
-dependencies = [
- "futures-channel",
- "futures-core",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
 [[package]]
 name = "go_to_line"
 version = "0.1.0"
@@ -2111,7 +1915,7 @@ checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d"
 dependencies = [
  "base64 0.13.0",
  "bitflags",
- "bytes 1.0.1",
+ "bytes",
  "headers-core",
  "http",
  "httpdate",
@@ -2158,16 +1962,6 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
-[[package]]
-name = "hkdf"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
-dependencies = [
- "digest 0.9.0",
- "hmac 0.10.1",
-]
-
 [[package]]
 name = "hmac"
 version = "0.10.1"
@@ -2194,7 +1988,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "fnv",
  "itoa 1.0.1",
 ]
@@ -2214,54 +2008,17 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "http",
  "pin-project-lite 0.2.8",
 ]
 
-[[package]]
-name = "http-client"
-version = "6.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce318d86a47d18d1db645c979214f809a6cd625202ad334ef75ca813b30dac80"
-dependencies = [
- "async-std",
- "async-trait",
- "cfg-if 1.0.0",
- "dashmap",
- "http-types",
- "isahc",
- "log",
-]
-
 [[package]]
 name = "http-range-header"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
 
-[[package]]
-name = "http-types"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad077d89137cd3debdce53c66714dc536525ef43fe075d41ddc0a8ac11f85957"
-dependencies = [
- "anyhow",
- "async-channel",
- "async-std",
- "base64 0.13.0",
- "cookie",
- "futures-lite",
- "infer",
- "pin-project-lite 0.2.8",
- "rand 0.7.3",
- "serde",
- "serde_json",
- "serde_qs",
- "serde_urlencoded",
- "url",
-]
-
 [[package]]
 name = "httparse"
 version = "1.7.0"
@@ -2286,7 +2043,7 @@ version = "0.14.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "futures-channel",
  "futures-core",
  "futures-util",
@@ -2370,12 +2127,6 @@ dependencies = [
  "unindent",
 ]
 
-[[package]]
-name = "infer"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac"
-
 [[package]]
 name = "instant"
 version = "0.1.9"
@@ -2415,19 +2166,23 @@ dependencies = [
 
 [[package]]
 name = "isahc"
-version = "0.9.14"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2948a0ce43e2c2ef11d7edf6816508998d99e13badd1150be0914205df9388a"
+checksum = "437f8808009c031df3c1d532c8fd7e3d73239dfe522ebf0b94b5e34d5d01044b"
 dependencies = [
- "bytes 0.5.6",
+ "async-channel",
+ "castaway",
  "crossbeam-utils 0.8.2",
  "curl",
  "curl-sys",
- "flume",
+ "encoding_rs",
+ "event-listener",
  "futures-lite",
  "http",
  "log",
+ "mime",
  "once_cell",
+ "polling",
  "slab",
  "sluice",
  "tracing",
@@ -2845,16 +2600,6 @@ version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
 
-[[package]]
-name = "mime_guess"
-version = "2.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
-dependencies = [
- "mime",
- "unicase",
-]
-
 [[package]]
 name = "miniz_oxide"
 version = "0.3.7"
@@ -3392,17 +3137,6 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6cce106fd2646acbe31a0e4006f75779d535c26a44f153ada196e9edcfc6d944"
 
-[[package]]
-name = "polyval"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd"
-dependencies = [
- "cpuid-bool",
- "opaque-debug",
- "universal-hash",
-]
-
 [[package]]
 name = "postage"
 version = "0.4.1"
@@ -3545,7 +3279,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "prost-derive",
 ]
 
@@ -3555,7 +3289,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "heck 0.3.3",
  "itertools",
  "log",
@@ -3586,7 +3320,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "prost",
 ]
 
@@ -4006,7 +3740,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c7c5f10864beba947e1a1b43f3ef46c8cc58d1c2ae549fa471713e8ff60787a"
 dependencies = [
- "cipher 0.3.0",
+ "cipher",
 ]
 
 [[package]]
@@ -4197,18 +3931,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "serde_qs"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5af82de3c6549b001bec34961ff2d6a54339a87bab37ce901b693401f27de6cb"
-dependencies = [
- "data-encoding",
- "percent-encoding",
- "serde",
- "thiserror",
-]
-
 [[package]]
 name = "serde_repr"
 version = "0.1.7"
@@ -4480,15 +4202,6 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
-[[package]]
-name = "spinning_top"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
-dependencies = [
- "lock_api",
-]
-
 [[package]]
 name = "sqlformat"
 version = "0.1.6"
@@ -4523,7 +4236,7 @@ dependencies = [
  "base64 0.13.0",
  "bitflags",
  "byteorder",
- "bytes 1.0.1",
+ "bytes",
  "crc",
  "crossbeam-channel 0.5.0",
  "crossbeam-queue",
@@ -4698,28 +4411,6 @@ dependencies = [
  "rand 0.8.3",
 ]
 
-[[package]]
-name = "surf"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a154d33ca6b5e1fe6fd1c760e5a5cc1202425f6cca2e13229f16a69009f6328"
-dependencies = [
- "async-std",
- "async-trait",
- "cfg-if 1.0.0",
- "encoding_rs",
- "futures-util",
- "http-client",
- "http-types",
- "log",
- "mime_guess",
- "once_cell",
- "pin-project-lite 0.2.8",
- "serde",
- "serde_json",
- "web-sys",
-]
-
 [[package]]
 name = "sval"
 version = "1.0.0-alpha.5"
@@ -5044,7 +4735,7 @@ version = "1.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "libc",
  "memchr",
  "mio 0.7.14",
@@ -5108,7 +4799,7 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764"
 dependencies = [
- "bytes 1.0.1",
+ "bytes",
  "futures-core",
  "futures-sink",
  "pin-project-lite 0.2.8",
@@ -5148,7 +4839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8"
 dependencies = [
  "bitflags",
- "bytes 1.0.1",
+ "bytes",
  "futures-core",
  "futures-util",
  "http",
@@ -5318,7 +5009,7 @@ checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1"
 dependencies = [
  "base64 0.13.0",
  "byteorder",
- "bytes 1.0.1",
+ "bytes",
  "http",
  "httparse",
  "log",
@@ -5337,7 +5028,7 @@ checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5"
 dependencies = [
  "base64 0.13.0",
  "byteorder",
- "bytes 1.0.1",
+ "bytes",
  "http",
  "httparse",
  "log",
@@ -5441,16 +5132,6 @@ version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8"
 
-[[package]]
-name = "universal-hash"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
-dependencies = [
- "generic-array",
- "subtle",
-]
-
 [[package]]
 name = "untrusted"
 version = "0.7.1"
@@ -5644,18 +5325,6 @@ dependencies = [
  "wasm-bindgen-shared",
 ]
 
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1"
-dependencies = [
- "cfg-if 1.0.0",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
 [[package]]
 name = "wasm-bindgen-macro"
 version = "0.2.74"
@@ -5901,6 +5570,7 @@ dependencies = [
  "ignore",
  "image",
  "indexmap",
+ "isahc",
  "journal",
  "language",
  "lazy_static",
@@ -5929,7 +5599,6 @@ dependencies = [
  "smallvec",
  "smol",
  "sum_tree",
- "surf",
  "tempdir",
  "text",
  "theme",

crates/auto_update/Cargo.toml 🔗

@@ -14,10 +14,10 @@ settings = { path = "../settings" }
 theme = { path = "../theme" }
 workspace = { path = "../workspace" }
 anyhow = "1.0.38"
+isahc = "1.7"
 lazy_static = "1.4"
 log = "0.4"
 serde = { version = "1", features = ["derive"] }
 serde_json = { version = "1.0.64", features = ["preserve_order"] }
 smol = "1.2.5"
-surf = "2.2"
 tempdir = "0.3.7"

crates/auto_update/src/auto_update.rs 🔗

@@ -1,5 +1,6 @@
-use anyhow::{anyhow, Result};
-use client::http::{self, HttpClient};
+use anyhow::{anyhow, Context, Result};
+use client::http::HttpClient;
+
 use gpui::{
     actions,
     elements::{Empty, MouseEventHandler, Text},
@@ -12,7 +13,6 @@ use serde::Deserialize;
 use settings::Settings;
 use smol::{fs::File, io::AsyncReadExt, process::Command};
 use std::{env, ffi::OsString, path::PathBuf, sync::Arc, time::Duration};
-use surf::Request;
 use workspace::{ItemHandle, StatusItemView};
 
 const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60);
@@ -52,7 +52,7 @@ pub struct AutoUpdateIndicator {
 #[derive(Deserialize)]
 struct JsonRelease {
     version: String,
-    url: http::Url,
+    url: String,
 }
 
 impl Entity for AutoUpdater {
@@ -134,17 +134,21 @@ impl AutoUpdater {
             )
         });
         let mut response = client
-            .send(Request::new(
-                http::Method::Get,
-                http::Url::parse(&format!(
-                    "{server_url}/api/releases/latest?token={ACCESS_TOKEN}&asset=Zed.dmg"
-                ))?,
-            ))
+            .get(
+                &format!("{server_url}/api/releases/latest?token={ACCESS_TOKEN}&asset=Zed.dmg"),
+                Default::default(),
+            )
             .await?;
-        let release = response
-            .body_json::<JsonRelease>()
+
+        let mut body = Vec::new();
+        response
+            .body_mut()
+            .read_to_end(&mut body)
             .await
-            .map_err(|err| anyhow!("error deserializing release {:?}", err))?;
+            .context("error reading release")?;
+        let release: JsonRelease =
+            serde_json::from_slice(body.as_slice()).context("error deserializing release")?;
+
         let latest_version = release.version.parse::<AppVersion>()?;
         if latest_version <= current_version {
             this.update(&mut cx, |this, cx| {
@@ -169,10 +173,8 @@ impl AutoUpdater {
             .map_or_else(|| cx.platform().app_path(), Ok)?;
 
         let mut dmg_file = File::create(&dmg_path).await?;
-        let response = client
-            .send(Request::new(http::Method::Get, release.url))
-            .await?;
-        smol::io::copy(response.bytes(), &mut dmg_file).await?;
+        let mut response = client.get(&release.url, Default::default()).await?;
+        smol::io::copy(response.body_mut(), &mut dmg_file).await?;
         log::info!("downloaded update. path:{:?}", dmg_path);
 
         this.update(&mut cx, |this, cx| {

crates/client/Cargo.toml 🔗

@@ -20,16 +20,17 @@ async-recursion = "0.3"
 async-tungstenite = { version = "0.16", features = ["async-tls"] }
 futures = "0.3"
 image = "0.23"
+isahc = "1.7"
 lazy_static = "1.4.0"
 log = { version = "0.4.16", features = ["kv_unstable_serde"] }
 parking_lot = "0.11.1"
 postage = { version = "0.4.1", features = ["futures-traits"] }
 rand = "0.8.3"
 smol = "1.2.5"
-surf = "2.2"
 thiserror = "1.0.29"
 time = "0.3"
 tiny_http = "0.8"
+url = "2.2"
 
 [dev-dependencies]
 gpui = { path = "../gpui", features = ["test-support"] }

crates/client/src/channel.rs 🔗

@@ -594,14 +594,13 @@ mod tests {
     use super::*;
     use crate::test::{FakeHttpClient, FakeServer};
     use gpui::TestAppContext;
-    use surf::http::Response;
 
     #[gpui::test]
     async fn test_channel_messages(cx: &mut TestAppContext) {
         cx.foreground().forbid_parking();
 
         let user_id = 5;
-        let http_client = FakeHttpClient::new(|_| async move { Ok(Response::new(404)) });
+        let http_client = FakeHttpClient::with_404_response();
         let mut client = Client::new(http_client.clone());
         let server = FakeServer::for_client(user_id, &mut client, &cx).await;
 

crates/client/src/client.rs 🔗

@@ -34,8 +34,8 @@ use std::{
     },
     time::{Duration, Instant},
 };
-use surf::{http::Method, Url};
 use thiserror::Error;
+use url::Url;
 use util::{ResultExt, TryFutureExt};
 
 pub use channel::*;
@@ -89,9 +89,11 @@ pub enum EstablishConnectionError {
     #[error("{0}")]
     Other(#[from] anyhow::Error),
     #[error("{0}")]
+    Http(#[from] http::Error),
+    #[error("{0}")]
     Io(#[from] std::io::Error),
     #[error("{0}")]
-    Http(#[from] async_tungstenite::tungstenite::http::Error),
+    Websocket(#[from] async_tungstenite::tungstenite::http::Error),
 }
 
 impl From<WebsocketError> for EstablishConnectionError {
@@ -779,30 +781,27 @@ impl Client {
         let http = self.http.clone();
         cx.background().spawn(async move {
             let mut rpc_url = format!("{}/rpc", *ZED_SERVER_URL);
-            let rpc_request = surf::Request::new(
-                Method::Get,
-                surf::Url::parse(&rpc_url).context("invalid ZED_SERVER_URL")?,
-            );
-            let rpc_response = http.send(rpc_request).await?;
-
+            let rpc_response = http.get(&rpc_url, Default::default()).await?;
             if rpc_response.status().is_redirection() {
                 rpc_url = rpc_response
-                    .header("Location")
+                    .headers()
+                    .get("Location")
                     .ok_or_else(|| anyhow!("missing location header in /rpc response"))?
-                    .as_str()
+                    .to_str()
+                    .map_err(|error| EstablishConnectionError::other(error))?
                     .to_string();
             }
             // Until we switch the zed.dev domain to point to the new Next.js app, there
             // will be no redirect required, and the app will connect directly to
             // wss://zed.dev/rpc.
-            else if rpc_response.status() != surf::StatusCode::UpgradeRequired {
+            else if rpc_response.status() != StatusCode::UPGRADE_REQUIRED {
                 Err(anyhow!(
                     "unexpected /rpc response status {}",
                     rpc_response.status()
                 ))?
             }
 
-            let mut rpc_url = surf::Url::parse(&rpc_url).context("invalid rpc url")?;
+            let mut rpc_url = Url::parse(&rpc_url).context("invalid rpc url")?;
             let rpc_host = rpc_url
                 .host_str()
                 .zip(rpc_url.port_or_known_default())

crates/client/src/http.rs 🔗

@@ -1,26 +1,45 @@
-pub use anyhow::{anyhow, Result};
 use futures::future::BoxFuture;
+use isahc::{
+    config::{Configurable, RedirectPolicy},
+    AsyncBody,
+};
 use std::sync::Arc;
-pub use surf::{
-    http::{Method, Response as ServerResponse},
-    Request, Response, Url,
+
+pub use anyhow::{anyhow, Result};
+pub use isahc::{
+    http::{Method, Uri},
+    Error,
 };
+pub use url::Url;
+
+pub type Request = isahc::Request<AsyncBody>;
+pub type Response = isahc::Response<AsyncBody>;
 
 pub trait HttpClient: Send + Sync {
-    fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response>>;
+    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>> {
+        self.send(
+            isahc::Request::builder()
+                .method(Method::GET)
+                .uri(uri)
+                .body(body)
+                .unwrap(),
+        )
+    }
 }
 
 pub fn client() -> Arc<dyn HttpClient> {
-    Arc::new(surf::client())
+    Arc::new(
+        isahc::HttpClient::builder()
+            .redirect_policy(RedirectPolicy::Follow)
+            .build()
+            .unwrap(),
+    )
 }
 
-impl HttpClient for surf::Client {
-    fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response>> {
-        Box::pin(async move {
-            Ok(self
-                .send(req)
-                .await
-                .map_err(|e| anyhow!("http request failed: {}", e))?)
-        })
+impl HttpClient for isahc::HttpClient {
+    fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response, Error>> {
+        Box::pin(async move { self.send_async(req).await })
     }
 }

crates/client/src/test.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{
-    http::{HttpClient, Request, Response, ServerResponse},
+    http::{self, HttpClient, Request, Response},
     Client, Connection, Credentials, EstablishConnectionError, UserStore,
 };
 use anyhow::{anyhow, Result};
@@ -176,14 +176,18 @@ impl FakeServer {
 }
 
 pub struct FakeHttpClient {
-    handler:
-        Box<dyn 'static + Send + Sync + Fn(Request) -> BoxFuture<'static, Result<ServerResponse>>>,
+    handler: Box<
+        dyn 'static
+            + Send
+            + Sync
+            + Fn(Request) -> BoxFuture<'static, Result<Response, http::Error>>,
+    >,
 }
 
 impl FakeHttpClient {
     pub fn new<Fut, F>(handler: F) -> Arc<dyn HttpClient>
     where
-        Fut: 'static + Send + Future<Output = Result<ServerResponse>>,
+        Fut: 'static + Send + Future<Output = Result<Response, http::Error>>,
         F: 'static + Send + Sync + Fn(Request) -> Fut,
     {
         Arc::new(Self {
@@ -192,7 +196,12 @@ impl FakeHttpClient {
     }
 
     pub fn with_404_response() -> Arc<dyn HttpClient> {
-        Self::new(|_| async move { Ok(ServerResponse::new(404)) })
+        Self::new(|_| async move {
+            Ok(isahc::Response::builder()
+                .status(404)
+                .body(Default::default())
+                .unwrap())
+        })
     }
 }
 
@@ -203,7 +212,7 @@ impl fmt::Debug for FakeHttpClient {
 }
 
 impl HttpClient for FakeHttpClient {
-    fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response>> {
+    fn send<'a>(&'a self, req: Request) -> BoxFuture<'a, Result<Response, crate::http::Error>> {
         let future = (self.handler)(req);
         Box::pin(async move { future.await.map(Into::into) })
     }

crates/client/src/user.rs 🔗

@@ -1,9 +1,6 @@
-use super::{
-    http::{HttpClient, Method, Request, Url},
-    proto, Client, Status, TypedEnvelope,
-};
-use anyhow::{anyhow, Context, Result};
-use futures::future;
+use super::{http::HttpClient, proto, Client, Status, TypedEnvelope};
+use anyhow::{anyhow, Result};
+use futures::{future, AsyncReadExt};
 use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
 use postage::{prelude::Stream, sink::Sink, watch};
 use std::{
@@ -255,22 +252,22 @@ impl Contact {
 }
 
 async fn fetch_avatar(http: &dyn HttpClient, url: &str) -> Result<Arc<ImageData>> {
-    let url = Url::parse(url).with_context(|| format!("failed to parse avatar url {:?}", url))?;
-    let mut request = Request::new(Method::Get, url);
-    request.middleware(surf::middleware::Redirect::default());
-
     let mut response = http
-        .send(request)
+        .get(url, Default::default())
         .await
         .map_err(|e| anyhow!("failed to send user avatar request: {}", e))?;
+
     if !response.status().is_success() {
         return Err(anyhow!("avatar request failed {:?}", response.status()));
     }
-    let bytes = response
-        .body_bytes()
+
+    let mut body = Vec::new();
+    response
+        .body_mut()
+        .read_to_end(&mut body)
         .await
         .map_err(|e| anyhow!("failed to read user avatar response body: {}", e))?;
-    let format = image::guess_format(&bytes)?;
-    let image = image::load_from_memory_with_format(&bytes, format)?.into_bgra8();
+    let format = image::guess_format(&body)?;
+    let image = image::load_from_memory_with_format(&body, format)?.into_bgra8();
     Ok(ImageData::new(image))
 }

crates/workspace/src/workspace.rs 🔗

@@ -623,9 +623,7 @@ impl WorkspaceParams {
 
         let fs = project::FakeFs::new(cx.background().clone());
         let languages = Arc::new(LanguageRegistry::test());
-        let http_client = client::test::FakeHttpClient::new(|_| async move {
-            Ok(client::http::ServerResponse::new(404))
-        });
+        let http_client = client::test::FakeHttpClient::with_404_response();
         let client = Client::new(http_client.clone());
         let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx));
         let project = Project::local(

crates/zed/Cargo.toml 🔗

@@ -62,6 +62,7 @@ http-auth-basic = "0.1.3"
 ignore = "0.4"
 image = "0.23"
 indexmap = "1.6.2"
+isahc = "1.7"
 lazy_static = "1.4.0"
 libc = "0.2"
 log = { version = "0.4.16", features = ["kv_unstable_serde"] }
@@ -79,7 +80,6 @@ serde_path_to_error = "0.1.4"
 simplelog = "0.9"
 smallvec = { version = "1.6", features = ["union"] }
 smol = "1.2.5"
-surf = "2.2"
 tempdir = { version = "0.3.7" }
 thiserror = "1.0.29"
 tiny_http = "0.8"

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

@@ -1,6 +1,6 @@
 use super::installation::{latest_github_release, GitHubLspBinaryVersion};
-use anyhow::{anyhow, Result};
-use client::http::{HttpClient, Method};
+use anyhow::{anyhow, Context, Result};
+use client::http::HttpClient;
 use futures::{future::BoxFuture, FutureExt, StreamExt};
 pub use language::*;
 use smol::fs::{self, File};
@@ -41,14 +41,10 @@ impl super::LspAdapter for CLspAdapter {
             let binary_path = version_dir.join("bin/clangd");
 
             if fs::metadata(&binary_path).await.is_err() {
-                let response = http
-                    .send(
-                        surf::RequestBuilder::new(Method::Get, version.url)
-                            .middleware(surf::middleware::Redirect::default())
-                            .build(),
-                    )
+                let mut response = http
+                    .get(&version.url, Default::default())
                     .await
-                    .map_err(|err| anyhow!("error downloading release: {}", err))?;
+                    .context("error downloading release")?;
                 let mut file = File::create(&zip_path).await?;
                 if !response.status().is_success() {
                     Err(anyhow!(
@@ -56,7 +52,7 @@ impl super::LspAdapter for CLspAdapter {
                         response.status().to_string()
                     ))?;
                 }
-                futures::io::copy(response, &mut file).await?;
+                futures::io::copy(response.body_mut(), &mut file).await?;
 
                 let unzip_status = smol::process::Command::new("unzip")
                     .current_dir(&container_dir)

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

@@ -1,11 +1,13 @@
 use anyhow::{anyhow, Context, Result};
-use client::http::{self, HttpClient, Method};
+use client::http::HttpClient;
+
 use serde::Deserialize;
+use smol::io::AsyncReadExt;
 use std::{path::Path, sync::Arc};
 
 pub struct GitHubLspBinaryVersion {
     pub name: String,
-    pub url: http::Url,
+    pub url: String,
 }
 
 #[derive(Deserialize)]
@@ -30,7 +32,7 @@ pub(crate) struct GithubRelease {
 #[derive(Deserialize)]
 pub(crate) struct GithubReleaseAsset {
     name: String,
-    browser_download_url: http::Url,
+    browser_download_url: String,
 }
 
 pub async fn npm_package_latest_version(name: &str) -> Result<String> {
@@ -81,23 +83,23 @@ pub async fn latest_github_release(
     http: Arc<dyn HttpClient>,
     asset_name: impl Fn(&str) -> String,
 ) -> Result<GitHubLspBinaryVersion> {
-    let release = http
-        .send(
-            surf::RequestBuilder::new(
-                Method::Get,
-                http::Url::parse(&format!(
-                    "https://api.github.com/repos/{repo_name_with_owner}/releases/latest"
-                ))
-                .unwrap(),
-            )
-            .middleware(surf::middleware::Redirect::default())
-            .build(),
+    let mut response = http
+        .get(
+            &format!("https://api.github.com/repos/{repo_name_with_owner}/releases/latest"),
+            Default::default(),
         )
         .await
-        .map_err(|err| anyhow!("error fetching latest release: {}", err))?
-        .body_json::<GithubRelease>()
+        .context("error fetching latest release")?;
+
+    let mut body = Vec::new();
+    response
+        .body_mut()
+        .read_to_end(&mut body)
         .await
-        .map_err(|err| anyhow!("error parsing latest release: {}", err))?;
+        .context("error reading latest release")?;
+
+    let release: GithubRelease =
+        serde_json::from_slice(body.as_slice()).context("error deserializing latest release")?;
     let asset_name = asset_name(&release.name);
     let asset = release
         .assets

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

@@ -1,8 +1,8 @@
 use super::installation::{latest_github_release, GitHubLspBinaryVersion};
 use anyhow::{anyhow, Result};
 use async_compression::futures::bufread::GzipDecoder;
-use client::http::{HttpClient, Method};
-use futures::{future::BoxFuture, FutureExt, StreamExt};
+use client::http::HttpClient;
+use futures::{future::BoxFuture, io::BufReader, FutureExt, StreamExt};
 pub use language::*;
 use lazy_static::lazy_static;
 use regex::Regex;
@@ -42,15 +42,11 @@ impl LspAdapter for RustLspAdapter {
             let destination_path = container_dir.join(format!("rust-analyzer-{}", version.name));
 
             if fs::metadata(&destination_path).await.is_err() {
-                let response = http
-                    .send(
-                        surf::RequestBuilder::new(Method::Get, version.url)
-                            .middleware(surf::middleware::Redirect::default())
-                            .build(),
-                    )
+                let mut response = http
+                    .get(&version.url, Default::default())
                     .await
                     .map_err(|err| anyhow!("error downloading release: {}", err))?;
-                let decompressed_bytes = GzipDecoder::new(response);
+                let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
                 let mut file = File::create(&destination_path).await?;
                 futures::io::copy(decompressed_bytes, &mut file).await?;
                 fs::set_permissions(