From 22ac178f9d1b8a62b71353bc39b805efb45ac9ee Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 11 Oct 2024 14:58:58 -0700 Subject: [PATCH] Restore HTTP client transition, but use reqwest everywhere (#19055) Release Notes: - N/A --- Cargo.lock | 585 ++++++++++++------ Cargo.toml | 16 +- crates/anthropic/Cargo.toml | 3 - crates/client/Cargo.toml | 3 +- crates/client/src/client.rs | 27 +- crates/collab/Cargo.toml | 4 +- crates/collab/src/llm.rs | 11 +- crates/collab/src/rpc.rs | 6 +- crates/evals/Cargo.toml | 2 +- crates/evals/src/eval.rs | 3 +- crates/extension/Cargo.toml | 3 +- crates/extension/src/extension_store_test.rs | 5 +- crates/extension_cli/Cargo.toml | 4 +- crates/extension_cli/src/main.rs | 9 +- crates/gpui/src/app.rs | 4 + crates/gpui/src/app/test_context.rs | 2 +- crates/http_client/Cargo.toml | 4 +- crates/http_client/src/http_client.rs | 56 +- crates/isahc_http_client/Cargo.toml | 22 - crates/isahc_http_client/LICENSE-APACHE | 1 - .../src/isahc_http_client.rs | 105 ---- crates/live_kit_server/Cargo.toml | 2 +- crates/reqwest_client/Cargo.toml | 34 + crates/reqwest_client/LICENSE-GPL | 1 + crates/reqwest_client/examples/client.rs | 41 ++ crates/reqwest_client/src/reqwest_client.rs | 261 ++++++++ crates/semantic_index/Cargo.toml | 2 +- crates/semantic_index/examples/index.rs | 5 +- crates/sqlez/src/util.rs | 6 +- crates/storybook/Cargo.toml | 2 +- crates/storybook/src/storybook.rs | 8 +- crates/util/src/util.rs | 2 +- crates/vim/Cargo.toml | 4 +- crates/zed/Cargo.toml | 2 +- crates/zed/src/main.rs | 11 +- 35 files changed, 838 insertions(+), 418 deletions(-) delete mode 100644 crates/isahc_http_client/Cargo.toml delete mode 120000 crates/isahc_http_client/LICENSE-APACHE delete mode 100644 crates/isahc_http_client/src/isahc_http_client.rs create mode 100644 crates/reqwest_client/Cargo.toml create mode 120000 crates/reqwest_client/LICENSE-GPL create mode 100644 crates/reqwest_client/examples/client.rs create mode 100644 crates/reqwest_client/src/reqwest_client.rs diff --git a/Cargo.lock b/Cargo.lock index 5f6218cb65..d9eb21ee26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,7 +250,6 @@ dependencies = [ "serde_json", "strum 0.25.0", "thiserror", - "tokio", "util", ] @@ -845,8 +844,8 @@ dependencies = [ "chrono", "futures-util", "http-types", - "hyper", - "hyper-rustls", + "hyper 0.14.30", + "hyper-rustls 0.24.2", "serde", "serde_json", "serde_path_to_error", @@ -879,15 +878,14 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-tls" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfeefd0ca297cbbb3bd34fd6b228401c2a5177038257afd751bc29f0a2da4795" +checksum = "b2ae3c9eba89d472a0e4fe1dea433df78fbbe63d2b764addaf2ba3a6bde89a5e" dependencies = [ "futures-core", "futures-io", - "rustls 0.20.9", + "rustls 0.21.12", "rustls-pemfile 1.0.4", - "webpki", "webpki-roots 0.22.6", ] @@ -904,9 +902,9 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.23.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc" +checksum = "90e661b6cb0a6eb34d02c520b052daa3aa9ac0cc02495c9d066bbce13ead132b" dependencies = [ "async-std", "async-tls", @@ -914,7 +912,7 @@ dependencies = [ "futures-util", "log", "pin-project-lite", - "tungstenite 0.20.1", + "tungstenite 0.24.0", ] [[package]] @@ -1063,7 +1061,7 @@ dependencies = [ "fastrand 2.1.1", "hex", "http 0.2.12", - "ring 0.17.8", + "ring", "time", "tokio", "tracing", @@ -1232,7 +1230,7 @@ dependencies = [ "once_cell", "p256", "percent-encoding", - "ring 0.17.8", + "ring", "sha2", "subtle", "time", @@ -1335,13 +1333,13 @@ dependencies = [ "aws-smithy-types", "bytes 1.7.1", "fastrand 2.1.1", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "http-body 1.0.1", "httparse", - "hyper", - "hyper-rustls", + "hyper 0.14.30", + "hyper-rustls 0.24.2", "once_cell", "pin-project-lite", "pin-utils", @@ -1431,7 +1429,7 @@ dependencies = [ "headers", "http 0.2.12", "http-body 0.4.6", - "hyper", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -1444,7 +1442,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", "tokio-tungstenite 0.20.1", "tower", @@ -1583,7 +1581,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn 2.0.76", ] @@ -1603,7 +1601,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn 2.0.76", ] @@ -2099,12 +2097,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -[[package]] -name = "castaway" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" - [[package]] name = "cbc" version = "0.1.2" @@ -2362,8 +2354,8 @@ dependencies = [ "clickhouse-derive", "clickhouse-rs-cityhash-sys", "futures 0.3.30", - "hyper", - "hyper-tls", + "hyper 0.14.30", + "hyper-tls 0.5.0", "lz4", "sealed", "serde", @@ -2401,6 +2393,7 @@ dependencies = [ "anyhow", "async-native-tls", "async-recursion 0.3.2", + "async-tls", "async-tungstenite", "chrono", "clock", @@ -2418,8 +2411,6 @@ dependencies = [ "rand 0.8.5", "release_channel", "rpc", - "rustls 0.20.9", - "rustls-native-certs 0.8.0", "schemars", "serde", "serde_json", @@ -2567,9 +2558,8 @@ dependencies = [ "headless", "hex", "http_client", - "hyper", + "hyper 0.14.30", "indoc", - "isahc_http_client", "jsonwebtoken", "language", "language_model", @@ -2593,7 +2583,8 @@ dependencies = [ "release_channel", "remote", "remote_server", - "reqwest", + "reqwest 0.11.27", + "reqwest_client", "rpc", "rustc-demangle", "scrypt", @@ -2677,7 +2668,7 @@ dependencies = [ name = "collections" version = "0.1.0" dependencies = [ - "rustc-hash", + "rustc-hash 1.1.0", ] [[package]] @@ -2995,7 +2986,7 @@ dependencies = [ "log", "rangemap", "rayon", - "rustc-hash", + "rustc-hash 1.1.0", "rustybuzz", "self_cell", "swash", @@ -3085,7 +3076,7 @@ dependencies = [ "hashbrown 0.14.5", "log", "regalloc2", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "target-lexicon", ] @@ -3341,36 +3332,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "curl" -version = "0.4.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2 0.5.7", - "windows-sys 0.52.0", -] - -[[package]] -name = "curl-sys" -version = "0.4.74+curl-8.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af10b986114528fcdc4b63b6f5f021b7057618411046a4de2ba0f0149a097bf" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "windows-sys 0.52.0", -] - [[package]] name = "cursor-icon" version = "1.1.0" @@ -4032,12 +3993,12 @@ dependencies = [ "git", "gpui", "http_client", - "isahc_http_client", "language", "languages", "node_runtime", "open_ai", "project", + "reqwest_client", "semantic_index", "serde", "serde_json", @@ -4127,7 +4088,6 @@ dependencies = [ "gpui", "http_client", "indexed_docs", - "isahc_http_client", "language", "log", "lsp", @@ -4136,6 +4096,7 @@ dependencies = [ "paths", "project", "release_channel", + "reqwest_client", "schemars", "semantic_version", "serde", @@ -4145,7 +4106,6 @@ dependencies = [ "snippet_provider", "task", "theme", - "tokio", "toml 0.8.19", "ui", "url", @@ -4167,9 +4127,9 @@ dependencies = [ "env_logger", "extension", "fs", - "isahc_http_client", "language", "log", + "reqwest_client", "rpc", "serde", "serde_json", @@ -4416,7 +4376,7 @@ dependencies = [ "futures-core", "futures-sink", "nanorand", - "spin 0.9.8", + "spin", ] [[package]] @@ -5182,6 +5142,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes 1.7.1", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.4.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.4.1" @@ -5550,8 +5529,10 @@ dependencies = [ "anyhow", "derive_more", "futures 0.3.30", - "http 0.2.12", + "http 1.1.0", "log", + "rustls 0.21.12", + "rustls-native-certs 0.8.0", "serde", "serde_json", "smol", @@ -5592,7 +5573,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -5606,6 +5587,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes 1.7.1", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -5614,12 +5615,29 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper", + "hyper 0.14.30", "log", "rustls 0.21.12", "rustls-native-certs 0.6.3", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "rustls 0.23.13", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", ] [[package]] @@ -5629,12 +5647,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes 1.7.1", - "hyper", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes 1.7.1", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes 1.7.1", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -6002,44 +6055,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "isahc" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" -dependencies = [ - "async-channel 1.9.0", - "castaway", - "crossbeam-utils", - "curl", - "curl-sys", - "encoding_rs", - "event-listener 2.5.3", - "futures-lite 1.13.0", - "http 0.2.12", - "log", - "mime", - "once_cell", - "polling 2.8.0", - "slab", - "sluice", - "tracing", - "tracing-futures", - "url", - "waker-fn", -] - -[[package]] -name = "isahc_http_client" -version = "0.1.0" -dependencies = [ - "anyhow", - "futures 0.3.30", - "http_client", - "isahc", - "util", -] - [[package]] name = "itertools" version = "0.10.5" @@ -6144,7 +6159,7 @@ dependencies = [ "base64 0.21.7", "js-sys", "pem", - "ring 0.17.8", + "ring", "serde", "serde_json", "simple_asn1", @@ -6395,7 +6410,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -6590,7 +6605,7 @@ dependencies = [ "prost", "prost-build", "prost-types", - "reqwest", + "reqwest 0.12.8", "serde", ] @@ -7074,7 +7089,7 @@ dependencies = [ "hexf-parse", "indexmap 2.4.0", "log", - "rustc-hash", + "rustc-hash 1.1.0", "spirv", "termcolor", "thiserror", @@ -8722,6 +8737,54 @@ dependencies = [ "zed_actions", ] +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes 1.7.1", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.0.0", + "rustls 0.23.13", + "socket2 0.5.7", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes 1.7.1", + "rand 0.8.5", + "ring", + "rustc-hash 2.0.0", + "rustls 0.23.13", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2 0.5.7", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.37" @@ -8998,7 +9061,7 @@ checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ "hashbrown 0.13.2", "log", - "rustc-hash", + "rustc-hash 1.1.0", "slice-group-by", "smallvec", ] @@ -9178,11 +9241,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper", - "hyper-tls", + "hyper 0.14.30", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -9195,8 +9258,8 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", - "system-configuration", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", "tower-service", @@ -9207,6 +9270,70 @@ dependencies = [ "winreg 0.50.0", ] +[[package]] +name = "reqwest" +version = "0.12.8" +source = "git+https://github.com/zed-industries/reqwest.git?rev=fd110f6998da16bbca97b6dddda9be7827c50e29#fd110f6998da16bbca97b6dddda9be7827c50e29" +dependencies = [ + "base64 0.22.1", + "bytes 1.7.1", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls 0.27.3", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.13", + "rustls-pemfile 2.1.3", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.26.0", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry", +] + +[[package]] +name = "reqwest_client" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes 1.7.1", + "futures 0.3.30", + "gpui", + "http_client", + "log", + "reqwest 0.12.8", + "serde", + "smol", + "tokio", +] + [[package]] name = "resvg" version = "0.41.0" @@ -9255,21 +9382,6 @@ dependencies = [ "util", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -9280,8 +9392,8 @@ dependencies = [ "cfg-if", "getrandom 0.2.15", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -9437,7 +9549,7 @@ dependencies = [ "futures 0.3.30", "glob", "rand 0.8.5", - "ring 0.17.8", + "ring", "serde", "serde_json", "shellexpand 3.1.0", @@ -9509,6 +9621,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc_version" version = "0.4.1" @@ -9558,18 +9676,6 @@ dependencies = [ "rustix 0.38.35", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.21.12" @@ -9577,11 +9683,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", - "rustls-webpki", + "ring", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -9638,8 +9758,19 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] @@ -9753,8 +9884,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -9950,7 +10081,6 @@ dependencies = [ "gpui", "heed", "http_client", - "isahc_http_client", "language", "language_model", "languages", @@ -9958,6 +10088,7 @@ dependencies = [ "open_ai", "parking_lot", "project", + "reqwest_client", "serde", "serde_json", "settings", @@ -10400,17 +10531,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "sluice" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" -dependencies = [ - "async-channel 1.9.0", - "futures-core", - "futures-io", -] - [[package]] name = "smallvec" version = "1.13.2" @@ -10525,12 +10645,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -10861,12 +10975,12 @@ dependencies = [ "fuzzy", "gpui", "indoc", - "isahc_http_client", "language", "log", "menu", "picker", "project", + "reqwest_client", "rust-embed", "settings", "simplelog", @@ -11162,6 +11276,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "synchronoise" version = "1.0.1" @@ -11202,7 +11325,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -11215,6 +11349,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -11592,7 +11736,7 @@ dependencies = [ "fancy-regex", "lazy_static", "parking_lot", - "rustc-hash", + "rustc-hash 1.1.0", ] [[package]] @@ -11808,6 +11952,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.13", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-socks" version = "0.5.2" @@ -11857,9 +12012,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes 1.7.1", "futures-core", @@ -12041,16 +12196,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -12357,6 +12502,24 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes 1.7.1", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror", + "utf-8", +] + [[package]] name = "typeid" version = "1.0.2" @@ -12515,12 +12678,6 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -12830,7 +12987,7 @@ dependencies = [ "futures-util", "headers", "http 0.2.12", - "hyper", + "hyper 0.14.30", "log", "mime", "mime_guess", @@ -12966,6 +13123,19 @@ dependencies = [ "wasmparser 0.201.0", ] +[[package]] +name = "wasm-streams" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.201.0" @@ -13381,8 +13551,8 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -13630,6 +13800,17 @@ dependencies = [ "syn 2.0.76", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -14421,7 +14602,6 @@ dependencies = [ "image_viewer", "inline_completion_button", "install_cli", - "isahc_http_client", "journal", "language", "language_model", @@ -14449,6 +14629,7 @@ dependencies = [ "release_channel", "remote", "repl", + "reqwest_client", "rope", "search", "serde", diff --git a/Cargo.toml b/Cargo.toml index 42f935e66b..f29d8041cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ members = [ "crates/indexed_docs", "crates/inline_completion_button", "crates/install_cli", - "crates/isahc_http_client", "crates/journal", "crates/language", "crates/language_model", @@ -88,6 +87,7 @@ members = [ "crates/remote", "crates/remote_server", "crates/repl", + "crates/reqwest_client", "crates/rich_text", "crates/rope", "crates/rpc", @@ -122,6 +122,7 @@ members = [ "crates/ui", "crates/ui_input", "crates/ui_macros", + "crates/reqwest_client", "crates/util", "crates/vcs_menu", "crates/vim", @@ -228,7 +229,6 @@ image_viewer = { path = "crates/image_viewer" } indexed_docs = { path = "crates/indexed_docs" } inline_completion_button = { path = "crates/inline_completion_button" } install_cli = { path = "crates/install_cli" } -isahc_http_client = { path = "crates/isahc_http_client" } journal = { path = "crates/journal" } language = { path = "crates/language" } language_model = { path = "crates/language_model" } @@ -265,6 +265,7 @@ release_channel = { path = "crates/release_channel" } remote = { path = "crates/remote" } remote_server = { path = "crates/remote_server" } repl = { path = "crates/repl" } +reqwest_client = { path = "crates/reqwest_client" } rich_text = { path = "crates/rich_text" } rope = { path = "crates/rope" } rpc = { path = "crates/rpc" } @@ -326,7 +327,7 @@ async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "8 async-recursion = "1.0.0" async-tar = "0.5.0" async-trait = "0.1" -async-tungstenite = "0.23" +async-tungstenite = "0.28" async-watch = "0.3.1" async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] } base64 = "0.22" @@ -366,10 +367,6 @@ ignore = "0.4.22" image = "0.25.1" indexmap = { version = "1.6.2", features = ["serde"] } indoc = "2" -# We explicitly disable http2 support in isahc. -isahc = { version = "1.7.2", default-features = false, features = [ - "text-decoding", -] } itertools = "0.13.0" jsonwebtoken = "9.3" libc = "0.2" @@ -394,13 +391,14 @@ pulldown-cmark = { version = "0.12.0", default-features = false } rand = "0.8.5" regex = "1.5" repair_json = "0.1.0" +reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "fd110f6998da16bbca97b6dddda9be7827c50e29" } rsa = "0.9.6" runtimelib = { version = "0.15", default-features = false, features = [ "async-dispatcher-runtime", ] } rustc-demangle = "0.1.23" rust-embed = { version = "8.4", features = ["include-exclude"] } -rustls = "0.20.3" +rustls = "0.21.12" rustls-native-certs = "0.8.0" schemars = { version = "0.8", features = ["impl_json_schema"] } semver = "1.0" @@ -438,7 +436,7 @@ time = { version = "0.3", features = [ ] } tiny_http = "0.8" toml = "0.8" -tokio = { version = "1", features = ["full"] } +tokio = { version = "1" } tower-http = "0.4.4" tree-sitter = { version = "0.23", features = ["wasm"] } tree-sitter-bash = "0.23" diff --git a/crates/anthropic/Cargo.toml b/crates/anthropic/Cargo.toml index ec12932fb7..32ac0fd988 100644 --- a/crates/anthropic/Cargo.toml +++ b/crates/anthropic/Cargo.toml @@ -26,6 +26,3 @@ serde_json.workspace = true strum.workspace = true thiserror.workspace = true util.workspace = true - -[dev-dependencies] -tokio.workspace = true diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index dd420bbbe6..c3fbea1f98 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -18,6 +18,7 @@ test-support = ["clock/test-support", "collections/test-support", "gpui/test-sup [dependencies] anyhow.workspace = true async-recursion = "0.3" +async-tls = "0.13" async-tungstenite = { workspace = true, features = ["async-std", "async-tls"] } chrono = { workspace = true, features = ["serde"] } clock.workspace = true @@ -34,8 +35,6 @@ postage.workspace = true rand.workspace = true release_channel.workspace = true rpc = { workspace = true, features = ["gpui"] } -rustls.workspace = true -rustls-native-certs.workspace = true schemars.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 7a37b1b405..03d81b117f 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1023,7 +1023,7 @@ impl Client { &self, http: Arc, release_channel: Option, - ) -> impl Future> { + ) -> impl Future> { #[cfg(any(test, feature = "test-support"))] let url_override = self.rpc_url.read().clone(); @@ -1117,7 +1117,7 @@ impl Client { // for us from the RPC URL. // // Among other things, it will generate and set a `Sec-WebSocket-Key` header for us. - let mut request = rpc_url.into_client_request()?; + let mut request = IntoClientRequest::into_client_request(rpc_url.as_str())?; // We then modify the request to add our desired headers. let request_headers = request.headers_mut(); @@ -1137,30 +1137,13 @@ impl Client { match url_scheme { Https => { - let client_config = { - let mut root_store = rustls::RootCertStore::empty(); - - let root_certs = rustls_native_certs::load_native_certs(); - for error in root_certs.errors { - log::warn!("error loading native certs: {:?}", error); - } - root_store.add_parsable_certificates( - &root_certs - .certs - .into_iter() - .map(|cert| cert.as_ref().to_owned()) - .collect::>(), - ); - rustls::ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(root_store) - .with_no_client_auth() - }; let (stream, _) = async_tungstenite::async_tls::client_async_tls_with_connector( request, stream, - Some(client_config.into()), + Some(async_tls::TlsConnector::from( + http_client::TLS_CONFIG.clone(), + )), ) .await?; Ok(Connection::new( diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 4513e02af3..ad2c013668 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -38,7 +38,6 @@ futures.workspace = true google_ai.workspace = true hex.workspace = true http_client.workspace = true -isahc_http_client.workspace = true jsonwebtoken.workspace = true live_kit_server.workspace = true log.workspace = true @@ -49,6 +48,7 @@ prometheus = "0.13" prost.workspace = true rand.workspace = true reqwest = { version = "0.11", features = ["json"] } +reqwest_client.workspace = true rpc.workspace = true rustc-demangle.workspace = true scrypt = "0.11" @@ -67,7 +67,7 @@ telemetry_events.workspace = true text.workspace = true thiserror.workspace = true time.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = ["full"] } toml.workspace = true tower = "0.4" tower-http = { workspace = true, features = ["trace"] } diff --git a/crates/collab/src/llm.rs b/crates/collab/src/llm.rs index 583cfdb7b8..a94aa5afe9 100644 --- a/crates/collab/src/llm.rs +++ b/crates/collab/src/llm.rs @@ -23,7 +23,7 @@ use collections::HashMap; use db::TokenUsage; use db::{usage_measure::UsageMeasure, ActiveUserCount, LlmDatabase}; use futures::{Stream, StreamExt as _}; -use isahc_http_client::IsahcHttpClient; +use reqwest_client::ReqwestClient; use rpc::{ proto::Plan, LanguageModelProvider, PerformCompletionParams, EXPIRED_LLM_TOKEN_HEADER_NAME, }; @@ -44,7 +44,7 @@ pub struct LlmState { pub config: Config, pub executor: Executor, pub db: Arc, - pub http_client: IsahcHttpClient, + pub http_client: ReqwestClient, pub clickhouse_client: Option, active_user_count_by_model: RwLock, ActiveUserCount)>>, @@ -70,11 +70,8 @@ impl LlmState { let db = Arc::new(db); let user_agent = format!("Zed Server/{}", env!("CARGO_PKG_VERSION")); - let http_client = IsahcHttpClient::builder() - .default_header("User-Agent", user_agent) - .build() - .map(IsahcHttpClient::from) - .context("failed to construct http client")?; + let http_client = + ReqwestClient::user_agent(&user_agent).context("failed to construct http client")?; let this = Self { executor, diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index e5dafe80d8..05d7726069 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -36,8 +36,8 @@ use collections::{HashMap, HashSet}; pub use connection_pool::{ConnectionPool, ZedVersion}; use core::fmt::{self, Debug, Formatter}; use http_client::HttpClient; -use isahc_http_client::IsahcHttpClient; use open_ai::{OpenAiEmbeddingModel, OPEN_AI_API_URL}; +use reqwest_client::ReqwestClient; use sha2::Digest; use supermaven_api::{CreateExternalUserRequest, SupermavenAdminApi}; @@ -961,8 +961,8 @@ impl Server { tracing::info!("connection opened"); let user_agent = format!("Zed Server/{}", env!("CARGO_PKG_VERSION")); - let http_client = match IsahcHttpClient::builder().default_header("User-Agent", user_agent).build() { - Ok(http_client) => Arc::new(IsahcHttpClient::from(http_client)), + let http_client = match ReqwestClient::user_agent(&user_agent) { + Ok(http_client) => Arc::new(http_client), Err(error) => { tracing::error!(?error, "failed to create HTTP client"); return; diff --git a/crates/evals/Cargo.toml b/crates/evals/Cargo.toml index b3b3a2f2a8..3057edcd1a 100644 --- a/crates/evals/Cargo.toml +++ b/crates/evals/Cargo.toml @@ -25,7 +25,6 @@ fs.workspace = true git.workspace = true gpui.workspace = true http_client.workspace = true -isahc_http_client.workspace = true language.workspace = true languages.workspace = true node_runtime.workspace = true @@ -36,3 +35,4 @@ serde.workspace = true serde_json.workspace = true settings.workspace = true smol.workspace = true +reqwest_client.workspace = true diff --git a/crates/evals/src/eval.rs b/crates/evals/src/eval.rs index 899d821053..2db13ff392 100644 --- a/crates/evals/src/eval.rs +++ b/crates/evals/src/eval.rs @@ -12,6 +12,7 @@ use language::LanguageRegistry; use node_runtime::NodeRuntime; use open_ai::OpenAiEmbeddingModel; use project::Project; +use reqwest_client::ReqwestClient; use semantic_index::{ EmbeddingProvider, OpenAiEmbeddingProvider, ProjectIndex, SemanticDb, Status, }; @@ -100,7 +101,7 @@ fn main() -> Result<()> { gpui::App::headless().run(move |cx| { let executor = cx.background_executor().clone(); - let client = isahc_http_client::IsahcHttpClient::new(None, None); + let client = Arc::new(ReqwestClient::user_agent("Zed LLM evals").unwrap()); cx.set_http_client(client.clone()); match cli.command { Commands::Fetch {} => { diff --git a/crates/extension/Cargo.toml b/crates/extension/Cargo.toml index f495ef7cdc..26b8610e76 100644 --- a/crates/extension/Cargo.toml +++ b/crates/extension/Cargo.toml @@ -56,7 +56,6 @@ wit-component.workspace = true workspace.workspace = true [dev-dependencies] -isahc_http_client.workspace = true ctor.workspace = true env_logger.workspace = true fs = { workspace = true, features = ["test-support"] } @@ -64,5 +63,5 @@ gpui = { workspace = true, features = ["test-support"] } language = { workspace = true, features = ["test-support"] } parking_lot.workspace = true project = { workspace = true, features = ["test-support"] } -tokio.workspace = true +reqwest_client.workspace = true workspace = { workspace = true, features = ["test-support"] } diff --git a/crates/extension/src/extension_store_test.rs b/crates/extension/src/extension_store_test.rs index 126e6b2cfb..1274fafc3c 100644 --- a/crates/extension/src/extension_store_test.rs +++ b/crates/extension/src/extension_store_test.rs @@ -13,12 +13,12 @@ use futures::{io::BufReader, AsyncReadExt, StreamExt}; use gpui::{Context, SemanticVersion, TestAppContext}; use http_client::{FakeHttpClient, Response}; use indexed_docs::IndexedDocsRegistry; -use isahc_http_client::IsahcHttpClient; use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName}; use node_runtime::NodeRuntime; use parking_lot::Mutex; use project::{Project, DEFAULT_COMPLETION_CONTEXT}; use release_channel::AppVersion; +use reqwest_client::ReqwestClient; use serde_json::json; use settings::{Settings as _, SettingsStore}; use snippet_provider::SnippetRegistry; @@ -576,7 +576,8 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { std::env::consts::ARCH ) }); - let builder_client = IsahcHttpClient::new(None, Some(user_agent)); + let builder_client = + Arc::new(ReqwestClient::user_agent(&user_agent).expect("Could not create HTTP client")); let extension_store = cx.new_model(|cx| { ExtensionStore::new( diff --git a/crates/extension_cli/Cargo.toml b/crates/extension_cli/Cargo.toml index bc649d8e04..6c7e3bdc62 100644 --- a/crates/extension_cli/Cargo.toml +++ b/crates/extension_cli/Cargo.toml @@ -18,14 +18,14 @@ clap = { workspace = true, features = ["derive"] } env_logger.workspace = true extension = { workspace = true, features = ["no-webrtc"] } fs.workspace = true -isahc_http_client.workspace = true language.workspace = true log.workspace = true +reqwest_client.workspace = true rpc.workspace = true serde.workspace = true serde_json.workspace = true theme.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = ["full"] } toml.workspace = true tree-sitter.workspace = true wasmtime.workspace = true diff --git a/crates/extension_cli/src/main.rs b/crates/extension_cli/src/main.rs index 6eaebca2f0..dd6f221378 100644 --- a/crates/extension_cli/src/main.rs +++ b/crates/extension_cli/src/main.rs @@ -13,8 +13,8 @@ use extension::{ extension_builder::{CompileExtensionOptions, ExtensionBuilder}, ExtensionManifest, }; -use isahc_http_client::IsahcHttpClient; use language::LanguageConfig; +use reqwest_client::ReqwestClient; use theme::ThemeRegistry; use tree_sitter::{Language, Query, WasmStore}; @@ -66,12 +66,7 @@ async fn main() -> Result<()> { std::env::consts::OS, std::env::consts::ARCH ); - let http_client = Arc::new( - IsahcHttpClient::builder() - .default_header("User-Agent", user_agent) - .build() - .map(IsahcHttpClient::from)?, - ); + let http_client = Arc::new(ReqwestClient::user_agent(&user_agent)?); let builder = ExtensionBuilder::new(http_client, scratch_dir); builder diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index bba5f857b4..f81a2092d5 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1533,4 +1533,8 @@ impl HttpClient for NullHttpClient { fn proxy(&self) -> Option<&http_client::Uri> { None } + + fn type_name(&self) -> &'static str { + type_name::() + } } diff --git a/crates/gpui/src/app/test_context.rs b/crates/gpui/src/app/test_context.rs index 95f0698855..f46cdc8e34 100644 --- a/crates/gpui/src/app/test_context.rs +++ b/crates/gpui/src/app/test_context.rs @@ -431,7 +431,7 @@ impl TestAppContext { rx } - /// Retuens a stream of events emitted by the given Model. + /// Returns a stream of events emitted by the given Model. pub fn events>( &mut self, entity: &Model, diff --git a/crates/http_client/Cargo.toml b/crates/http_client/Cargo.toml index 0244ac4104..e8585cff98 100644 --- a/crates/http_client/Cargo.toml +++ b/crates/http_client/Cargo.toml @@ -16,11 +16,13 @@ path = "src/http_client.rs" doctest = true [dependencies] -http = "0.2" anyhow.workspace = true derive_more.workspace = true futures.workspace = true +http = "1.1" log.workspace = true +rustls-native-certs.workspace = true +rustls.workspace = true serde.workspace = true serde_json.workspace = true smol.workspace = true diff --git a/crates/http_client/src/http_client.rs b/crates/http_client/src/http_client.rs index 2f029a1d23..bf1046d88e 100644 --- a/crates/http_client/src/http_client.rs +++ b/crates/http_client/src/http_client.rs @@ -11,13 +11,22 @@ use http::request::Builder; #[cfg(feature = "test-support")] use std::fmt; use std::{ - sync::{Arc, Mutex}, + any::type_name, + sync::{Arc, LazyLock, Mutex}, time::Duration, }; pub use url::Url; +#[derive(Clone)] pub struct ReadTimeout(pub Duration); -#[derive(Default, Debug, Clone)] +impl Default for ReadTimeout { + fn default() -> Self { + Self(Duration::from_secs(5)) + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] + pub enum RedirectPolicy { #[default] NoFollow, @@ -26,6 +35,23 @@ pub enum RedirectPolicy { } pub struct FollowRedirects(pub bool); +pub static TLS_CONFIG: LazyLock> = LazyLock::new(|| { + let mut root_store = rustls::RootCertStore::empty(); + + let root_certs = rustls_native_certs::load_native_certs(); + for error in root_certs.errors { + log::warn!("error loading native certs: {:?}", error); + } + root_store.add_parsable_certificates(&root_certs.certs); + + Arc::new( + rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(root_store) + .with_no_client_auth(), + ) +}); + pub trait HttpRequestExt { /// Set a read timeout on the request. /// For isahc, this is the low_speed_timeout. @@ -47,6 +73,8 @@ impl HttpRequestExt for http::request::Builder { } pub trait HttpClient: 'static + Send + Sync { + fn type_name(&self) -> &'static str; + fn send( &self, req: http::Request, @@ -129,6 +157,10 @@ impl HttpClient for HttpClientWithProxy { fn proxy(&self) -> Option<&Uri> { self.proxy.as_ref() } + + fn type_name(&self) -> &'static str { + self.client.type_name() + } } impl HttpClient for Arc { @@ -142,6 +174,10 @@ impl HttpClient for Arc { fn proxy(&self) -> Option<&Uri> { self.proxy.as_ref() } + + fn type_name(&self) -> &'static str { + self.client.type_name() + } } /// An [`HttpClient`] that has a base URL. @@ -253,6 +289,10 @@ impl HttpClient for Arc { fn proxy(&self) -> Option<&Uri> { self.client.proxy.as_ref() } + + fn type_name(&self) -> &'static str { + self.client.type_name() + } } impl HttpClient for HttpClientWithUrl { @@ -266,6 +306,10 @@ impl HttpClient for HttpClientWithUrl { fn proxy(&self) -> Option<&Uri> { self.client.proxy.as_ref() } + + fn type_name(&self) -> &'static str { + self.client.type_name() + } } pub fn read_proxy_from_env() -> Option { @@ -306,6 +350,10 @@ impl HttpClient for BlockedHttpClient { fn proxy(&self) -> Option<&Uri> { None } + + fn type_name(&self) -> &'static str { + type_name::() + } } #[cfg(feature = "test-support")] @@ -378,4 +426,8 @@ impl HttpClient for FakeHttpClient { fn proxy(&self) -> Option<&Uri> { None } + + fn type_name(&self) -> &'static str { + type_name::() + } } diff --git a/crates/isahc_http_client/Cargo.toml b/crates/isahc_http_client/Cargo.toml deleted file mode 100644 index 82f7621bf8..0000000000 --- a/crates/isahc_http_client/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "isahc_http_client" -version = "0.1.0" -edition = "2021" -publish = false -license = "Apache-2.0" - -[lints] -workspace = true - -[features] -test-support = [] - -[lib] -path = "src/isahc_http_client.rs" - -[dependencies] -anyhow.workspace = true -futures.workspace = true -http_client.workspace = true -isahc.workspace = true -util.workspace = true diff --git a/crates/isahc_http_client/LICENSE-APACHE b/crates/isahc_http_client/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3..0000000000 --- a/crates/isahc_http_client/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/crates/isahc_http_client/src/isahc_http_client.rs b/crates/isahc_http_client/src/isahc_http_client.rs deleted file mode 100644 index 778f6a0459..0000000000 --- a/crates/isahc_http_client/src/isahc_http_client.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::{mem, sync::Arc, time::Duration}; - -use futures::future::BoxFuture; -use util::maybe; - -pub use isahc::config::Configurable; -pub struct IsahcHttpClient(isahc::HttpClient); - -pub use http_client::*; - -impl IsahcHttpClient { - pub fn new(proxy: Option, user_agent: Option) -> Arc { - let mut builder = isahc::HttpClient::builder() - .connect_timeout(Duration::from_secs(5)) - .low_speed_timeout(100, Duration::from_secs(5)) - .proxy(proxy.clone()); - if let Some(agent) = user_agent { - builder = builder.default_header("User-Agent", agent); - } - Arc::new(IsahcHttpClient(builder.build().unwrap())) - } - pub fn builder() -> isahc::HttpClientBuilder { - isahc::HttpClientBuilder::new() - } -} - -impl From for IsahcHttpClient { - fn from(client: isahc::HttpClient) -> Self { - Self(client) - } -} - -impl HttpClient for IsahcHttpClient { - fn proxy(&self) -> Option<&Uri> { - None - } - - fn send( - &self, - req: http_client::http::Request, - ) -> BoxFuture<'static, Result, anyhow::Error>> - { - let redirect_policy = req - .extensions() - .get::() - .cloned() - .unwrap_or_default(); - let read_timeout = req - .extensions() - .get::() - .map(|t| t.0); - let req = maybe!({ - let (mut parts, body) = req.into_parts(); - let mut builder = isahc::Request::builder() - .method(parts.method) - .uri(parts.uri) - .version(parts.version); - if let Some(read_timeout) = read_timeout { - builder = builder.low_speed_timeout(100, read_timeout); - } - - let headers = builder.headers_mut()?; - mem::swap(headers, &mut parts.headers); - - let extensions = builder.extensions_mut()?; - mem::swap(extensions, &mut parts.extensions); - - let isahc_body = match body.0 { - http_client::Inner::Empty => isahc::AsyncBody::empty(), - http_client::Inner::AsyncReader(reader) => isahc::AsyncBody::from_reader(reader), - http_client::Inner::SyncReader(reader) => { - isahc::AsyncBody::from_bytes_static(reader.into_inner()) - } - }; - - builder - .redirect_policy(match redirect_policy { - http_client::RedirectPolicy::FollowAll => isahc::config::RedirectPolicy::Follow, - http_client::RedirectPolicy::FollowLimit(limit) => { - isahc::config::RedirectPolicy::Limit(limit) - } - http_client::RedirectPolicy::NoFollow => isahc::config::RedirectPolicy::None, - }) - .body(isahc_body) - .ok() - }); - - let client = self.0.clone(); - - Box::pin(async move { - match req { - Some(req) => client - .send_async(req) - .await - .map_err(Into::into) - .map(|response| { - let (parts, body) = response.into_parts(); - let body = http_client::AsyncBody::from_reader(body); - http_client::Response::from_parts(parts, body) - }), - None => Err(anyhow::anyhow!("Request was malformed")), - } - }) - } -} diff --git a/crates/live_kit_server/Cargo.toml b/crates/live_kit_server/Cargo.toml index bad4c5a05f..4b4b5e13da 100644 --- a/crates/live_kit_server/Cargo.toml +++ b/crates/live_kit_server/Cargo.toml @@ -20,7 +20,7 @@ jsonwebtoken.workspace = true log.workspace = true prost.workspace = true prost-types.workspace = true -reqwest = "0.11" +reqwest.workspace = true serde.workspace = true [build-dependencies] diff --git a/crates/reqwest_client/Cargo.toml b/crates/reqwest_client/Cargo.toml new file mode 100644 index 0000000000..1246aa4eef --- /dev/null +++ b/crates/reqwest_client/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "reqwest_client" +version = "0.1.0" +edition = "2021" +publish = false +license = "Apache-2.0" + +[lints] +workspace = true + +[features] +test-support = [] + +[lib] +path = "src/reqwest_client.rs" +doctest = true + +[[example]] +name = "client" +path = "examples/client.rs" + +[dependencies] +anyhow.workspace = true +bytes = "1.0" +futures.workspace = true +http_client.workspace = true +serde.workspace = true +smol.workspace = true +log.workspace = true +tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } +reqwest = { workspace = true, features = ["rustls-tls-manual-roots", "stream"] } + +[dev-dependencies] +gpui.workspace = true diff --git a/crates/reqwest_client/LICENSE-GPL b/crates/reqwest_client/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/reqwest_client/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/reqwest_client/examples/client.rs b/crates/reqwest_client/examples/client.rs new file mode 100644 index 0000000000..d94c4cec5f --- /dev/null +++ b/crates/reqwest_client/examples/client.rs @@ -0,0 +1,41 @@ +use std::time::Instant; + +use futures::stream::FuturesUnordered; +use futures::AsyncReadExt as _; +use http_client::AsyncBody; +use http_client::HttpClient; +use reqwest_client::ReqwestClient; +use smol::stream::StreamExt; + +fn main() { + let app = gpui::App::new(); + app.run(|cx| { + cx.spawn(|cx| async move { + let client = ReqwestClient::new(); + let start = Instant::now(); + let requests = [ + client.get("https://www.google.com/", AsyncBody::empty(), true), + client.get("https://zed.dev/", AsyncBody::empty(), true), + client.get("https://docs.rs/", AsyncBody::empty(), true), + ]; + let mut requests = requests.into_iter().collect::>(); + while let Some(response) = requests.next().await { + let mut body = String::new(); + response + .unwrap() + .into_body() + .read_to_string(&mut body) + .await + .unwrap(); + println!("{}", &body.len()); + } + println!("{:?}", start.elapsed()); + + cx.update(|cx| { + cx.quit(); + }) + .ok(); + }) + .detach(); + }) +} diff --git a/crates/reqwest_client/src/reqwest_client.rs b/crates/reqwest_client/src/reqwest_client.rs new file mode 100644 index 0000000000..7b0e66f2a5 --- /dev/null +++ b/crates/reqwest_client/src/reqwest_client.rs @@ -0,0 +1,261 @@ +use std::{any::type_name, borrow::Cow, io::Read, mem, pin::Pin, sync::OnceLock, task::Poll}; + +use anyhow::anyhow; +use bytes::{BufMut, Bytes, BytesMut}; +use futures::{AsyncRead, TryStreamExt}; +use http_client::{http, ReadTimeout, RedirectPolicy}; +use reqwest::{ + header::{HeaderMap, HeaderValue}, + redirect, +}; +use smol::future::FutureExt; + +const DEFAULT_CAPACITY: usize = 4096; + +pub struct ReqwestClient { + client: reqwest::Client, + proxy: Option, + handle: tokio::runtime::Handle, +} + +impl ReqwestClient { + pub fn new() -> Self { + reqwest::Client::new().into() + } + + pub fn user_agent(agent: &str) -> anyhow::Result { + let mut map = HeaderMap::new(); + map.insert(http::header::USER_AGENT, HeaderValue::from_str(agent)?); + let client = reqwest::Client::builder().default_headers(map).build()?; + Ok(client.into()) + } + + pub fn proxy_and_user_agent(proxy: Option, agent: &str) -> anyhow::Result { + let mut map = HeaderMap::new(); + map.insert(http::header::USER_AGENT, HeaderValue::from_str(agent)?); + let mut client = reqwest::Client::builder().default_headers(map); + if let Some(proxy) = proxy.clone() { + client = client.proxy(reqwest::Proxy::all(proxy.to_string())?); + } + let client = client.build()?; + let mut client: ReqwestClient = client.into(); + client.proxy = proxy; + Ok(client) + } +} + +static RUNTIME: OnceLock = OnceLock::new(); + +impl From for ReqwestClient { + fn from(client: reqwest::Client) -> Self { + let handle = tokio::runtime::Handle::try_current().unwrap_or_else(|_| { + log::info!("no tokio runtime found, creating one for Reqwest..."); + let runtime = RUNTIME.get_or_init(|| { + tokio::runtime::Builder::new_multi_thread() + // Since we now have two executors, let's try to keep our footprint small + .worker_threads(1) + .enable_all() + .build() + .expect("Failed to initialize HTTP client") + }); + + runtime.handle().clone() + }); + Self { + client, + handle, + proxy: None, + } + } +} + +// This struct is essentially a re-implementation of +// https://docs.rs/tokio-util/0.7.12/tokio_util/io/struct.ReaderStream.html +// except outside of Tokio's aegis +struct StreamReader { + reader: Option>>, + buf: BytesMut, + capacity: usize, +} + +impl StreamReader { + fn new(reader: Pin>) -> Self { + Self { + reader: Some(reader), + buf: BytesMut::new(), + capacity: DEFAULT_CAPACITY, + } + } +} + +impl futures::Stream for StreamReader { + type Item = std::io::Result; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + let mut this = self.as_mut(); + + let mut reader = match this.reader.take() { + Some(r) => r, + None => return Poll::Ready(None), + }; + + if this.buf.capacity() == 0 { + let capacity = this.capacity; + this.buf.reserve(capacity); + } + + match poll_read_buf(&mut reader, cx, &mut this.buf) { + Poll::Pending => Poll::Pending, + Poll::Ready(Err(err)) => { + self.reader = None; + + Poll::Ready(Some(Err(err))) + } + Poll::Ready(Ok(0)) => { + self.reader = None; + Poll::Ready(None) + } + Poll::Ready(Ok(_)) => { + let chunk = this.buf.split(); + self.reader = Some(reader); + Poll::Ready(Some(Ok(chunk.freeze()))) + } + } + } +} + +/// Implementation from https://docs.rs/tokio-util/0.7.12/src/tokio_util/util/poll_buf.rs.html +/// Specialized for this use case +pub fn poll_read_buf( + io: &mut Pin>, + cx: &mut std::task::Context<'_>, + buf: &mut BytesMut, +) -> Poll> { + if !buf.has_remaining_mut() { + return Poll::Ready(Ok(0)); + } + + let n = { + let dst = buf.chunk_mut(); + + // Safety: `chunk_mut()` returns a `&mut UninitSlice`, and `UninitSlice` is a + // transparent wrapper around `[MaybeUninit]`. + let dst = unsafe { &mut *(dst as *mut _ as *mut [std::mem::MaybeUninit]) }; + let mut buf = tokio::io::ReadBuf::uninit(dst); + let ptr = buf.filled().as_ptr(); + let unfilled_portion = buf.initialize_unfilled(); + // SAFETY: Pin projection + let io_pin = unsafe { Pin::new_unchecked(io) }; + std::task::ready!(io_pin.poll_read(cx, unfilled_portion)?); + + // Ensure the pointer does not change from under us + assert_eq!(ptr, buf.filled().as_ptr()); + buf.filled().len() + }; + + // Safety: This is guaranteed to be the number of initialized (and read) + // bytes due to the invariants provided by `ReadBuf::filled`. + unsafe { + buf.advance_mut(n); + } + + Poll::Ready(Ok(n)) +} + +struct SyncReader { + cursor: Option>>, +} + +impl SyncReader { + fn new(cursor: std::io::Cursor>) -> Self { + Self { + cursor: Some(cursor), + } + } +} + +impl futures::stream::Stream for SyncReader { + type Item = Result; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + _cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + let Some(mut cursor) = self.cursor.take() else { + return Poll::Ready(None); + }; + + let mut buf = Vec::new(); + match cursor.read_to_end(&mut buf) { + Ok(_) => { + return Poll::Ready(Some(Ok(Bytes::from(buf)))); + } + Err(e) => return Poll::Ready(Some(Err(e))), + } + } +} + +impl http_client::HttpClient for ReqwestClient { + fn proxy(&self) -> Option<&http::Uri> { + self.proxy.as_ref() + } + + fn type_name(&self) -> &'static str { + type_name::() + } + + fn send( + &self, + req: http::Request, + ) -> futures::future::BoxFuture< + 'static, + Result, anyhow::Error>, + > { + let (parts, body) = req.into_parts(); + + let mut request = self.client.request(parts.method, parts.uri.to_string()); + request = request.headers(parts.headers); + if let Some(redirect_policy) = parts.extensions.get::() { + request = request.redirect_policy(match redirect_policy { + RedirectPolicy::NoFollow => redirect::Policy::none(), + RedirectPolicy::FollowLimit(limit) => redirect::Policy::limited(*limit as usize), + RedirectPolicy::FollowAll => redirect::Policy::limited(100), + }); + } + if let Some(ReadTimeout(timeout)) = parts.extensions.get::() { + request = request.timeout(*timeout); + } + let request = request.body(match body.0 { + http_client::Inner::Empty => reqwest::Body::default(), + http_client::Inner::SyncReader(cursor) => { + reqwest::Body::wrap_stream(SyncReader::new(cursor)) + } + http_client::Inner::AsyncReader(stream) => { + reqwest::Body::wrap_stream(StreamReader::new(stream)) + } + }); + + let handle = self.handle.clone(); + async move { + let mut response = handle.spawn(async { request.send().await }).await??; + + let headers = mem::take(response.headers_mut()); + let mut builder = http::Response::builder() + .status(response.status().as_u16()) + .version(response.version()); + *builder.headers_mut().unwrap() = headers; + + let bytes = response + .bytes_stream() + .map_err(|e| futures::io::Error::new(futures::io::ErrorKind::Other, e)) + .into_async_read(); + let body = http_client::AsyncBody::from_reader(bytes); + + builder.body(body).map_err(|e| anyhow!(e)) + } + .boxed() + } +} diff --git a/crates/semantic_index/Cargo.toml b/crates/semantic_index/Cargo.toml index f157cc9b3f..d6d43f4916 100644 --- a/crates/semantic_index/Cargo.toml +++ b/crates/semantic_index/Cargo.toml @@ -51,7 +51,6 @@ workspace.workspace = true worktree.workspace = true [dev-dependencies] -isahc_http_client.workspace = true client = { workspace = true, features = ["test-support"] } env_logger.workspace = true fs = { workspace = true, features = ["test-support"] } @@ -62,6 +61,7 @@ language = { workspace = true, features = ["test-support"] } languages.workspace = true project = { workspace = true, features = ["test-support"] } tempfile.workspace = true +reqwest_client.workspace = true util = { workspace = true, features = ["test-support"] } workspace = { workspace = true, features = ["test-support"] } worktree = { workspace = true, features = ["test-support"] } diff --git a/crates/semantic_index/examples/index.rs b/crates/semantic_index/examples/index.rs index c5c2c633a1..2efd94cb57 100644 --- a/crates/semantic_index/examples/index.rs +++ b/crates/semantic_index/examples/index.rs @@ -2,7 +2,6 @@ use client::Client; use futures::channel::oneshot; use gpui::App; use http_client::HttpClientWithUrl; -use isahc_http_client::IsahcHttpClient; use language::language_settings::AllLanguageSettings; use project::Project; use semantic_index::{OpenAiEmbeddingModel, OpenAiEmbeddingProvider, SemanticDb}; @@ -29,7 +28,9 @@ fn main() { let clock = Arc::new(FakeSystemClock::default()); let http = Arc::new(HttpClientWithUrl::new( - IsahcHttpClient::new(None, None), + Arc::new( + reqwest_client::ReqwestClient::user_agent("Zed semantic index example").unwrap(), + ), "http://localhost:11434", None, )); diff --git a/crates/sqlez/src/util.rs b/crates/sqlez/src/util.rs index ce0353b15e..8be6d3f4e0 100644 --- a/crates/sqlez/src/util.rs +++ b/crates/sqlez/src/util.rs @@ -9,14 +9,14 @@ use thread_local::ThreadLocal; /// Note: this locks on the cloneable sender, but its done once per thread, so it /// shouldn't result in too much contention pub struct UnboundedSyncSender { - clonable_sender: Mutex>, + cloneable_sender: Mutex>, local_senders: ThreadLocal>, } impl UnboundedSyncSender { pub fn new(sender: Sender) -> Self { Self { - clonable_sender: Mutex::new(sender), + cloneable_sender: Mutex::new(sender), local_senders: ThreadLocal::new(), } } @@ -27,6 +27,6 @@ impl Deref for UnboundedSyncSender { fn deref(&self) -> &Self::Target { self.local_senders - .get_or(|| self.clonable_sender.lock().clone()) + .get_or(|| self.cloneable_sender.lock().clone()) } } diff --git a/crates/storybook/Cargo.toml b/crates/storybook/Cargo.toml index f8e78acad3..a27079489b 100644 --- a/crates/storybook/Cargo.toml +++ b/crates/storybook/Cargo.toml @@ -22,7 +22,6 @@ editor.workspace = true fuzzy.workspace = true gpui.workspace = true indoc.workspace = true -isahc_http_client.workspace = true language.workspace = true log.workspace = true menu.workspace = true @@ -36,6 +35,7 @@ strum = { workspace = true, features = ["derive"] } theme.workspace = true title_bar = { workspace = true, features = ["stories"] } ui = { workspace = true, features = ["stories"] } +reqwest_client.workspace = true [dev-dependencies] gpui = { workspace = true, features = ["test-support"] } diff --git a/crates/storybook/src/storybook.rs b/crates/storybook/src/storybook.rs index 73b1396da5..9fe61a70c4 100644 --- a/crates/storybook/src/storybook.rs +++ b/crates/storybook/src/storybook.rs @@ -4,15 +4,17 @@ mod assets; mod stories; mod story_selector; +use std::sync::Arc; + use clap::Parser; use dialoguer::FuzzySelect; use gpui::{ div, px, size, AnyView, AppContext, Bounds, Render, ViewContext, VisualContext, WindowBounds, WindowOptions, }; -use isahc_http_client::IsahcHttpClient; use log::LevelFilter; use project::Project; +use reqwest_client::ReqwestClient; use settings::{KeymapFile, Settings}; use simplelog::SimpleLogger; use strum::IntoEnumIterator; @@ -66,8 +68,8 @@ fn main() { gpui::App::new().with_assets(Assets).run(move |cx| { load_embedded_fonts(cx).unwrap(); - let http_client = IsahcHttpClient::new(None, Some("zed_storybook".to_string())); - cx.set_http_client(http_client); + let http_client = ReqwestClient::user_agent("zed_storybook").unwrap(); + cx.set_http_client(Arc::new(http_client)); settings::init(cx); theme::init(theme::LoadThemes::All(Box::new(Assets)), cx); diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 50fc070009..1330c3f749 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -729,7 +729,7 @@ mod tests { } #[test] - fn test_trancate_and_trailoff() { + fn test_truncate_and_trailoff() { assert_eq!(truncate_and_trailoff("", 5), ""); assert_eq!(truncate_and_trailoff("èèèèèè", 7), "èèèèèè"); assert_eq!(truncate_and_trailoff("èèèèèè", 6), "èèèèèè"); diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index 410371cb0c..fddb607c1f 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -17,7 +17,7 @@ neovim = ["nvim-rs", "async-compat", "async-trait", "tokio"] [dependencies] anyhow.workspace = true -async-compat = { version = "0.2.1", "optional" = true } +async-compat = { workspace = true, "optional" = true } async-trait = { workspace = true, "optional" = true } collections.workspace = true command_palette.workspace = true @@ -36,7 +36,7 @@ serde.workspace = true serde_derive.workspace = true serde_json.workspace = true settings.workspace = true -tokio = { version = "1.15", "optional" = true } +tokio = { version = "1.15", features = ["full"], optional = true } ui.workspace = true util.workspace = true workspace.workspace = true diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 0ec26ea7cd..a271019573 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -57,7 +57,6 @@ http_client.workspace = true image_viewer.workspace = true inline_completion_button.workspace = true install_cli.workspace = true -isahc_http_client.workspace = true journal.workspace = true language.workspace = true language_model.workspace = true @@ -108,6 +107,7 @@ theme.workspace = true theme_selector.workspace = true time.workspace = true ui.workspace = true +reqwest_client.workspace = true url.workspace = true urlencoding = "2.1.2" util.workspace = true diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index cd245dc12c..6652e23504 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -24,9 +24,9 @@ use gpui::{ UpdateGlobal as _, VisualContext, }; use http_client::{read_proxy_from_env, Uri}; -use isahc_http_client::IsahcHttpClient; use language::LanguageRegistry; use log::LevelFilter; +use reqwest_client::ReqwestClient; use assets::Assets; use node_runtime::{NodeBinaryOptions, NodeRuntime}; @@ -335,9 +335,7 @@ fn main() { log::info!("========== starting zed =========="); - let app = App::new() - .with_assets(Assets) - .with_http_client(IsahcHttpClient::new(None, None)); + let app = App::new().with_assets(Assets); let system_id = app.background_executor().block(system_id()).ok(); let installation_id = app.background_executor().block(installation_id()).ok(); @@ -471,8 +469,9 @@ fn main() { .ok() }) .or_else(read_proxy_from_env); - let http = IsahcHttpClient::new(proxy_url, Some(user_agent)); - cx.set_http_client(http); + let http = ReqwestClient::proxy_and_user_agent(proxy_url, &user_agent) + .expect("could not start HTTP client"); + cx.set_http_client(Arc::new(http)); ::set_global(fs.clone(), cx);