From 5d5c4b667741246c521c161cda792b9ad29fc102 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 9 Oct 2024 01:07:18 -0700 Subject: [PATCH] Revert http client changes (#18892) These proved to be too unstable. Will restore these changes once the issues have been fixed. Release Notes: - N/A --- Cargo.lock | 603 ++++++------------ Cargo.toml | 15 +- crates/client/Cargo.toml | 3 +- crates/client/src/client.rs | 27 +- crates/collab/Cargo.toml | 2 +- crates/collab/src/llm.rs | 12 +- crates/collab/src/rpc.rs | 6 +- crates/evals/Cargo.toml | 2 +- crates/evals/src/eval.rs | 7 +- crates/extension/Cargo.toml | 3 +- crates/extension/src/extension_builder.rs | 2 +- crates/extension/src/extension_store_test.rs | 52 +- crates/extension_cli/Cargo.toml | 2 +- crates/extension_cli/src/main.rs | 9 +- crates/gpui/src/app.rs | 4 - crates/http_client/Cargo.toml | 4 +- crates/http_client/src/http_client.rs | 56 +- .../Cargo.toml | 15 +- 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 | 31 - crates/reqwest_client/LICENSE-GPL | 1 - crates/reqwest_client/examples/client.rs | 16 - crates/reqwest_client/src/reqwest_client.rs | 259 -------- crates/semantic_index/Cargo.toml | 2 +- crates/semantic_index/examples/index.rs | 7 +- crates/storybook/Cargo.toml | 2 +- crates/storybook/src/storybook.rs | 12 +- crates/ureq_client/LICENSE-GPL | 1 - crates/ureq_client/examples/client.rs | 24 - crates/ureq_client/src/ureq_client.rs | 200 ------ crates/vim/Cargo.toml | 2 +- crates/zed/Cargo.toml | 2 +- crates/zed/src/main.rs | 10 +- 35 files changed, 381 insertions(+), 1120 deletions(-) rename crates/{ureq_client => isahc_http_client}/Cargo.toml (53%) create mode 120000 crates/isahc_http_client/LICENSE-APACHE create mode 100644 crates/isahc_http_client/src/isahc_http_client.rs delete mode 100644 crates/reqwest_client/Cargo.toml delete mode 120000 crates/reqwest_client/LICENSE-GPL delete mode 100644 crates/reqwest_client/examples/client.rs delete mode 100644 crates/reqwest_client/src/reqwest_client.rs delete mode 120000 crates/ureq_client/LICENSE-GPL delete mode 100644 crates/ureq_client/examples/client.rs delete mode 100644 crates/ureq_client/src/ureq_client.rs diff --git a/Cargo.lock b/Cargo.lock index 1bae8d9850318..cc588fcb22cb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -846,8 +846,8 @@ dependencies = [ "chrono", "futures-util", "http-types", - "hyper 0.14.30", - "hyper-rustls 0.24.2", + "hyper", + "hyper-rustls", "serde", "serde_json", "serde_path_to_error", @@ -880,14 +880,15 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-tls" -version = "0.13.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ae3c9eba89d472a0e4fe1dea433df78fbbe63d2b764addaf2ba3a6bde89a5e" +checksum = "cfeefd0ca297cbbb3bd34fd6b228401c2a5177038257afd751bc29f0a2da4795" dependencies = [ "futures-core", "futures-io", - "rustls 0.21.12", + "rustls 0.20.9", "rustls-pemfile 1.0.4", + "webpki", "webpki-roots 0.22.6", ] @@ -904,9 +905,9 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.28.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e661b6cb0a6eb34d02c520b052daa3aa9ac0cc02495c9d066bbce13ead132b" +checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc" dependencies = [ "async-std", "async-tls", @@ -914,7 +915,7 @@ dependencies = [ "futures-util", "log", "pin-project-lite", - "tungstenite 0.24.0", + "tungstenite 0.20.1", ] [[package]] @@ -1063,7 +1064,7 @@ dependencies = [ "fastrand 2.1.1", "hex", "http 0.2.12", - "ring", + "ring 0.17.8", "time", "tokio", "tracing", @@ -1232,7 +1233,7 @@ dependencies = [ "once_cell", "p256", "percent-encoding", - "ring", + "ring 0.17.8", "sha2", "subtle", "time", @@ -1335,13 +1336,13 @@ dependencies = [ "aws-smithy-types", "bytes 1.7.1", "fastrand 2.1.1", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", "http-body 1.0.1", "httparse", - "hyper 0.14.30", - "hyper-rustls 0.24.2", + "hyper", + "hyper-rustls", "once_cell", "pin-project-lite", "pin-utils", @@ -1431,7 +1432,7 @@ dependencies = [ "headers", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper", "itoa", "matchit", "memchr", @@ -1444,7 +1445,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", "tokio-tungstenite 0.20.1", "tower", @@ -1583,7 +1584,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", "syn 2.0.76", ] @@ -1603,7 +1604,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", "syn 2.0.76", ] @@ -2099,6 +2100,12 @@ 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" @@ -2356,8 +2363,8 @@ dependencies = [ "clickhouse-derive", "clickhouse-rs-cityhash-sys", "futures 0.3.30", - "hyper 0.14.30", - "hyper-tls 0.5.0", + "hyper", + "hyper-tls", "lz4", "sealed", "serde", @@ -2395,7 +2402,6 @@ dependencies = [ "anyhow", "async-native-tls", "async-recursion 0.3.2", - "async-tls", "async-tungstenite", "chrono", "clock", @@ -2413,6 +2419,8 @@ dependencies = [ "rand 0.8.5", "release_channel", "rpc", + "rustls 0.20.9", + "rustls-native-certs 0.8.0", "schemars", "serde", "serde_json", @@ -2559,8 +2567,9 @@ dependencies = [ "headless", "hex", "http_client", - "hyper 0.14.30", + "hyper", "indoc", + "isahc_http_client", "jsonwebtoken", "language", "language_model", @@ -2584,8 +2593,7 @@ dependencies = [ "release_channel", "remote", "remote_server", - "reqwest 0.11.27", - "reqwest_client", + "reqwest", "rpc", "rustc-demangle", "scrypt", @@ -2669,7 +2677,7 @@ dependencies = [ name = "collections" version = "0.1.0" dependencies = [ - "rustc-hash 1.1.0", + "rustc-hash", ] [[package]] @@ -2987,7 +2995,7 @@ dependencies = [ "log", "rangemap", "rayon", - "rustc-hash 1.1.0", + "rustc-hash", "rustybuzz", "self_cell", "swash", @@ -3077,7 +3085,7 @@ dependencies = [ "hashbrown 0.14.5", "log", "regalloc2", - "rustc-hash 1.1.0", + "rustc-hash", "smallvec", "target-lexicon", ] @@ -3333,6 +3341,36 @@ 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" @@ -3994,6 +4032,7 @@ dependencies = [ "git", "gpui", "http_client", + "isahc_http_client", "language", "languages", "node_runtime", @@ -4004,7 +4043,6 @@ dependencies = [ "serde_json", "settings", "smol", - "ureq_client", ] [[package]] @@ -4089,6 +4127,7 @@ dependencies = [ "gpui", "http_client", "indexed_docs", + "isahc_http_client", "language", "log", "lsp", @@ -4097,7 +4136,6 @@ dependencies = [ "paths", "project", "release_channel", - "reqwest_client", "schemars", "semantic_version", "serde", @@ -4110,7 +4148,6 @@ dependencies = [ "tokio", "toml 0.8.19", "ui", - "ureq_client", "url", "util", "wasm-encoder 0.215.0", @@ -4130,9 +4167,9 @@ dependencies = [ "env_logger", "extension", "fs", + "isahc_http_client", "language", "log", - "reqwest_client", "rpc", "serde", "serde_json", @@ -4379,7 +4416,7 @@ dependencies = [ "futures-core", "futures-sink", "nanorand", - "spin", + "spin 0.9.8", ] [[package]] @@ -5145,25 +5182,6 @@ 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" @@ -5544,10 +5562,8 @@ dependencies = [ "anyhow", "derive_more", "futures 0.3.30", - "http 1.1.0", + "http 0.2.12", "log", - "rustls 0.21.12", - "rustls-native-certs 0.8.0", "serde", "serde_json", "smol", @@ -5588,7 +5604,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -5602,26 +5618,6 @@ 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" @@ -5630,29 +5626,12 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper", "log", "rustls 0.21.12", "rustls-native-certs 0.6.3", "tokio", - "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", + "tokio-rustls", ] [[package]] @@ -5662,47 +5641,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes 1.7.1", - "hyper 0.14.30", + "hyper", "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" @@ -6070,6 +6014,44 @@ 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" @@ -6174,7 +6156,7 @@ dependencies = [ "base64 0.21.7", "js-sys", "pem", - "ring", + "ring 0.17.8", "serde", "serde_json", "simple_asn1", @@ -6424,7 +6406,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -6619,7 +6601,7 @@ dependencies = [ "prost", "prost-build", "prost-types", - "reqwest 0.12.8", + "reqwest", "serde", ] @@ -7103,7 +7085,7 @@ dependencies = [ "hexf-parse", "indexmap 2.4.0", "log", - "rustc-hash 1.1.0", + "rustc-hash", "spirv", "termcolor", "thiserror", @@ -8751,54 +8733,6 @@ 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" @@ -9075,7 +9009,7 @@ checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ "hashbrown 0.13.2", "log", - "rustc-hash 1.1.0", + "rustc-hash", "slice-group-by", "smallvec", ] @@ -9254,11 +9188,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", - "hyper-tls 0.5.0", + "hyper", + "hyper-tls", "ipnet", "js-sys", "log", @@ -9271,8 +9205,8 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration 0.5.1", + "sync_wrapper", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -9283,68 +9217,6 @@ 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", - "http_client", - "reqwest 0.12.8", - "serde", - "smol", - "tokio", -] - [[package]] name = "resvg" version = "0.41.0" @@ -9393,6 +9265,21 @@ 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" @@ -9403,8 +9290,8 @@ dependencies = [ "cfg-if", "getrandom 0.2.15", "libc", - "spin", - "untrusted", + "spin 0.9.8", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -9560,7 +9447,7 @@ dependencies = [ "futures 0.3.30", "glob", "rand 0.8.5", - "ring", + "ring 0.17.8", "serde", "serde_json", "shellexpand 3.1.0", @@ -9632,12 +9519,6 @@ 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" @@ -9689,28 +9570,26 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ "log", - "ring", - "rustls-webpki 0.101.7", + "ring 0.16.20", "sct", + "webpki", ] [[package]] name = "rustls" -version = "0.23.13" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", + "log", + "ring 0.17.8", + "rustls-webpki", + "sct", ] [[package]] @@ -9769,19 +9648,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "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", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -9895,8 +9763,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -10092,6 +9960,7 @@ dependencies = [ "gpui", "heed", "http_client", + "isahc_http_client", "language", "language_model", "languages", @@ -10109,7 +9978,6 @@ dependencies = [ "tree-sitter", "ui", "unindent", - "ureq_client", "util", "workspace", "worktree", @@ -10542,6 +10410,17 @@ 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" @@ -10656,6 +10535,12 @@ 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" @@ -10986,6 +10871,7 @@ dependencies = [ "fuzzy", "gpui", "indoc", + "isahc_http_client", "language", "log", "menu", @@ -10999,7 +10885,6 @@ dependencies = [ "theme", "title_bar", "ui", - "ureq_client", ] [[package]] @@ -11287,15 +11172,6 @@ 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" @@ -11336,18 +11212,7 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "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", + "system-configuration-sys", ] [[package]] @@ -11360,16 +11225,6 @@ 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" @@ -11747,7 +11602,7 @@ dependencies = [ "fancy-regex", "lazy_static", "parking_lot", - "rustc-hash 1.1.0", + "rustc-hash", ] [[package]] @@ -11963,17 +11818,6 @@ 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" @@ -12023,9 +11867,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes 1.7.1", "futures-core", @@ -12207,6 +12051,16 @@ 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" @@ -12513,24 +12367,6 @@ 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" @@ -12691,40 +12527,15 @@ checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "untrusted" -version = "0.9.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] -name = "ureq" -version = "2.9.1" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" -dependencies = [ - "base64 0.21.7", - "flate2", - "log", - "once_cell", - "rustls 0.21.12", - "rustls-webpki 0.101.7", - "url", - "webpki-roots 0.25.4", -] - -[[package]] -name = "ureq_client" -version = "0.1.0" -dependencies = [ - "anyhow", - "futures 0.3.30", - "gpui", - "http_client", - "parking_lot", - "serde", - "smol", - "ureq", - "util", -] +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -13029,7 +12840,7 @@ dependencies = [ "futures-util", "headers", "http 0.2.12", - "hyper 0.14.30", + "hyper", "log", "mime", "mime_guess", @@ -13165,19 +12976,6 @@ 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" @@ -13593,8 +13391,8 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -13851,17 +13649,6 @@ 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" @@ -14653,6 +14440,7 @@ dependencies = [ "image_viewer", "inline_completion_button", "install_cli", + "isahc_http_client", "journal", "language", "language_model", @@ -14705,7 +14493,6 @@ dependencies = [ "tree-sitter-md", "tree-sitter-rust", "ui", - "ureq_client", "url", "urlencoding", "util", diff --git a/Cargo.toml b/Cargo.toml index 6fc22029e7a4f..887d9fb55a4e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ members = [ "crates/indexed_docs", "crates/inline_completion_button", "crates/install_cli", + "crates/isahc_http_client", "crates/journal", "crates/language", "crates/language_model", @@ -87,7 +88,6 @@ members = [ "crates/remote", "crates/remote_server", "crates/repl", - "crates/reqwest_client", "crates/rich_text", "crates/rope", "crates/rpc", @@ -122,7 +122,6 @@ members = [ "crates/ui", "crates/ui_input", "crates/ui_macros", - "crates/ureq_client", "crates/util", "crates/vcs_menu", "crates/vim", @@ -230,6 +229,7 @@ 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" } @@ -266,7 +266,6 @@ 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" } @@ -301,7 +300,6 @@ title_bar = { path = "crates/title_bar" } ui = { path = "crates/ui" } ui_input = { path = "crates/ui_input" } ui_macros = { path = "crates/ui_macros" } -ureq_client = { path = "crates/ureq_client" } util = { path = "crates/util" } vcs_menu = { path = "crates/vcs_menu" } vim = { path = "crates/vim" } @@ -329,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.28" +async-tungstenite = "0.23" async-watch = "0.3.1" async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] } base64 = "0.22" @@ -369,6 +367,10 @@ 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" @@ -393,14 +395,13 @@ 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.21.12" +rustls = "0.20.3" rustls-native-certs = "0.8.0" schemars = { version = "0.8", features = ["impl_json_schema"] } semver = "1.0" diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index c3fbea1f98a88..dd420bbbe6318 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -18,7 +18,6 @@ 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 @@ -35,6 +34,8 @@ 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 03d81b117f37e..7a37b1b40556b 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 = IntoClientRequest::into_client_request(rpc_url.as_str())?; + let mut request = rpc_url.into_client_request()?; // We then modify the request to add our desired headers. let request_headers = request.headers_mut(); @@ -1137,13 +1137,30 @@ 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(async_tls::TlsConnector::from( - http_client::TLS_CONFIG.clone(), - )), + Some(client_config.into()), ) .await?; Ok(Connection::new( diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index de7a3c621465e..48482bd435622 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -37,6 +37,7 @@ 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 @@ -47,7 +48,6 @@ 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" diff --git a/crates/collab/src/llm.rs b/crates/collab/src/llm.rs index 96413cf7c5671..86563a766cdea 100644 --- a/crates/collab/src/llm.rs +++ b/crates/collab/src/llm.rs @@ -22,8 +22,7 @@ use chrono::{DateTime, Duration, Utc}; use collections::HashMap; use db::{usage_measure::UsageMeasure, ActiveUserCount, LlmDatabase}; use futures::{Stream, StreamExt as _}; - -use reqwest_client::ReqwestClient; +use isahc_http_client::IsahcHttpClient; use rpc::ListModelsResponse; use rpc::{ proto::Plan, LanguageModelProvider, PerformCompletionParams, EXPIRED_LLM_TOKEN_HEADER_NAME, @@ -44,7 +43,7 @@ pub struct LlmState { pub config: Config, pub executor: Executor, pub db: Arc, - pub http_client: ReqwestClient, + pub http_client: IsahcHttpClient, pub clickhouse_client: Option, active_user_count_by_model: RwLock, ActiveUserCount)>>, @@ -70,8 +69,11 @@ impl LlmState { let db = Arc::new(db); let user_agent = format!("Zed Server/{}", env!("CARGO_PKG_VERSION")); - let http_client = - ReqwestClient::user_agent(&user_agent).context("failed to construct http client")?; + let http_client = IsahcHttpClient::builder() + .default_header("User-Agent", user_agent) + .build() + .map(IsahcHttpClient::from) + .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 e66c306c506dd..95e2e620419bd 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}; @@ -964,8 +964,8 @@ impl Server { tracing::info!("connection opened"); let user_agent = format!("Zed Server/{}", env!("CARGO_PKG_VERSION")); - let http_client = match ReqwestClient::user_agent(&user_agent) { - Ok(http_client) => Arc::new(http_client), + let http_client = match IsahcHttpClient::builder().default_header("User-Agent", user_agent).build() { + Ok(http_client) => Arc::new(IsahcHttpClient::from(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 2697b768453f1..b3b3a2f2a8010 100644 --- a/crates/evals/Cargo.toml +++ b/crates/evals/Cargo.toml @@ -25,6 +25,7 @@ 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 @@ -35,4 +36,3 @@ serde.workspace = true serde_json.workspace = true settings.workspace = true smol.workspace = true -ureq_client.workspace = true diff --git a/crates/evals/src/eval.rs b/crates/evals/src/eval.rs index e2dc5c8e03a2f..899d821053711 100644 --- a/crates/evals/src/eval.rs +++ b/crates/evals/src/eval.rs @@ -32,7 +32,6 @@ use std::{ Arc, }, }; -use ureq_client::UreqClient; const CODESEARCH_NET_DIR: &'static str = "target/datasets/code-search-net"; const EVAL_REPOS_DIR: &'static str = "target/datasets/eval-repos"; @@ -101,11 +100,7 @@ fn main() -> Result<()> { gpui::App::headless().run(move |cx| { let executor = cx.background_executor().clone(); - let client = Arc::new(UreqClient::new( - None, - "Zed LLM evals".to_string(), - executor.clone(), - )); + let client = isahc_http_client::IsahcHttpClient::new(None, None); cx.set_http_client(client.clone()); match cli.command { Commands::Fetch {} => { diff --git a/crates/extension/Cargo.toml b/crates/extension/Cargo.toml index 2b1d6193f8669..f495ef7cdc992 100644 --- a/crates/extension/Cargo.toml +++ b/crates/extension/Cargo.toml @@ -56,6 +56,7 @@ 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"] } @@ -63,7 +64,5 @@ gpui = { workspace = true, features = ["test-support"] } language = { workspace = true, features = ["test-support"] } parking_lot.workspace = true project = { workspace = true, features = ["test-support"] } -reqwest_client.workspace = true tokio.workspace = true -ureq_client.workspace = true workspace = { workspace = true, features = ["test-support"] } diff --git a/crates/extension/src/extension_builder.rs b/crates/extension/src/extension_builder.rs index 876d0336dc707..7380e699f9e71 100644 --- a/crates/extension/src/extension_builder.rs +++ b/crates/extension/src/extension_builder.rs @@ -25,7 +25,7 @@ use wit_component::ComponentEncoder; /// Once Rust 1.78 is released, there will be a `wasm32-wasip2` target available, so we will /// not need the adapter anymore. const RUST_TARGET: &str = "wasm32-wasip1"; -pub const WASI_ADAPTER_URL: &str = +const WASI_ADAPTER_URL: &str = "https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasi_snapshot_preview1.reactor.wasm"; /// Compiling Tree-sitter parsers from C to WASM requires Clang 17, and a WASM build of libc diff --git a/crates/extension/src/extension_store_test.rs b/crates/extension/src/extension_store_test.rs index 7a3c645e041a1..126e6b2cfbdad 100644 --- a/crates/extension/src/extension_store_test.rs +++ b/crates/extension/src/extension_store_test.rs @@ -1,4 +1,3 @@ -use crate::extension_builder::WASI_ADAPTER_URL; use crate::extension_manifest::SchemaVersion; use crate::extension_settings::ExtensionSettings; use crate::{ @@ -12,14 +11,14 @@ use collections::BTreeMap; use fs::{FakeFs, Fs, RealFs}; use futures::{io::BufReader, AsyncReadExt, StreamExt}; use gpui::{Context, SemanticVersion, TestAppContext}; -use http_client::{AsyncBody, FakeHttpClient, HttpClient, Response}; +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; @@ -29,7 +28,6 @@ use std::{ sync::Arc, }; use theme::ThemeRegistry; -use ureq_client::UreqClient; use util::test::temp_tree; #[cfg(test)] @@ -578,7 +576,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { std::env::consts::ARCH ) }); - let builder_client = Arc::new(UreqClient::new(None, user_agent, cx.executor().clone())); + let builder_client = IsahcHttpClient::new(None, Some(user_agent)); let extension_store = cx.new_model(|cx| { ExtensionStore::new( @@ -771,50 +769,6 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { assert!(fs.metadata(&expected_server_path).await.unwrap().is_none()); } -#[gpui::test] -async fn test_wasi_adapter_download(cx: &mut TestAppContext) { - let client = Arc::new(UreqClient::new( - None, - "zed-test-wasi-adapter-download".to_string(), - cx.executor().clone(), - )); - - let mut response = client - .get(WASI_ADAPTER_URL, AsyncBody::default(), true) - .await - .unwrap(); - - let mut content = Vec::new(); - let mut body = BufReader::new(response.body_mut()); - body.read_to_end(&mut content).await.unwrap(); - - assert!(wasmparser::Parser::is_core_wasm(&content)); - assert_eq!(content.len(), 96801); // Determined by downloading this to my computer - wit_component::ComponentEncoder::default() - .adapter("wasi_snapshot_preview1", &content) - .unwrap(); -} - -#[tokio::test] -async fn test_wasi_adapter_download_tokio() { - let client = Arc::new(ReqwestClient::new()); - - let mut response = client - .get(WASI_ADAPTER_URL, AsyncBody::default(), true) - .await - .unwrap(); - - let mut content = Vec::new(); - let mut body = BufReader::new(response.body_mut()); - body.read_to_end(&mut content).await.unwrap(); - - assert!(wasmparser::Parser::is_core_wasm(&content)); - assert_eq!(content.len(), 96801); // Determined by downloading this to my computer - wit_component::ComponentEncoder::default() - .adapter("wasi_snapshot_preview1", &content) - .unwrap(); -} - fn init_test(cx: &mut TestAppContext) { cx.update(|cx| { let store = SettingsStore::test(cx); diff --git a/crates/extension_cli/Cargo.toml b/crates/extension_cli/Cargo.toml index 6de3e858d4fff..bc649d8e04989 100644 --- a/crates/extension_cli/Cargo.toml +++ b/crates/extension_cli/Cargo.toml @@ -18,9 +18,9 @@ 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 diff --git a/crates/extension_cli/src/main.rs b/crates/extension_cli/src/main.rs index dd6f221378119..6eaebca2f0e9b 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,7 +66,12 @@ async fn main() -> Result<()> { std::env::consts::OS, std::env::consts::ARCH ); - let http_client = Arc::new(ReqwestClient::user_agent(&user_agent)?); + let http_client = Arc::new( + IsahcHttpClient::builder() + .default_header("User-Agent", user_agent) + .build() + .map(IsahcHttpClient::from)?, + ); let builder = ExtensionBuilder::new(http_client, scratch_dir); builder diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index f81a2092d56af..bba5f857b4f52 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1533,8 +1533,4 @@ impl HttpClient for NullHttpClient { fn proxy(&self) -> Option<&http_client::Uri> { None } - - fn type_name(&self) -> &'static str { - type_name::() - } } diff --git a/crates/http_client/Cargo.toml b/crates/http_client/Cargo.toml index e8585cff9820f..0244ac41042b6 100644 --- a/crates/http_client/Cargo.toml +++ b/crates/http_client/Cargo.toml @@ -16,13 +16,11 @@ 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 bf1046d88ee82..2f029a1d236bb 100644 --- a/crates/http_client/src/http_client.rs +++ b/crates/http_client/src/http_client.rs @@ -11,22 +11,13 @@ use http::request::Builder; #[cfg(feature = "test-support")] use std::fmt; use std::{ - any::type_name, - sync::{Arc, LazyLock, Mutex}, + sync::{Arc, Mutex}, time::Duration, }; pub use url::Url; -#[derive(Clone)] pub struct ReadTimeout(pub Duration); -impl Default for ReadTimeout { - fn default() -> Self { - Self(Duration::from_secs(5)) - } -} - -#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] - +#[derive(Default, Debug, Clone)] pub enum RedirectPolicy { #[default] NoFollow, @@ -35,23 +26,6 @@ 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. @@ -73,8 +47,6 @@ impl HttpRequestExt for http::request::Builder { } pub trait HttpClient: 'static + Send + Sync { - fn type_name(&self) -> &'static str; - fn send( &self, req: http::Request, @@ -157,10 +129,6 @@ 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 { @@ -174,10 +142,6 @@ 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. @@ -289,10 +253,6 @@ 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 { @@ -306,10 +266,6 @@ 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 { @@ -350,10 +306,6 @@ impl HttpClient for BlockedHttpClient { fn proxy(&self) -> Option<&Uri> { None } - - fn type_name(&self) -> &'static str { - type_name::() - } } #[cfg(feature = "test-support")] @@ -426,8 +378,4 @@ impl HttpClient for FakeHttpClient { fn proxy(&self) -> Option<&Uri> { None } - - fn type_name(&self) -> &'static str { - type_name::() - } } diff --git a/crates/ureq_client/Cargo.toml b/crates/isahc_http_client/Cargo.toml similarity index 53% rename from crates/ureq_client/Cargo.toml rename to crates/isahc_http_client/Cargo.toml index 757ba010946c7..82f7621bf8cac 100644 --- a/crates/ureq_client/Cargo.toml +++ b/crates/isahc_http_client/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ureq_client" +name = "isahc_http_client" version = "0.1.0" edition = "2021" publish = false @@ -12,20 +12,11 @@ workspace = true test-support = [] [lib] -path = "src/ureq_client.rs" -doctest = true - -[[example]] -name = "client" -path = "examples/client.rs" +path = "src/isahc_http_client.rs" [dependencies] anyhow.workspace = true futures.workspace = true -gpui.workspace = true http_client.workspace = true -parking_lot.workspace = true -serde.workspace = true -smol.workspace = true -ureq = "=2.9.1" +isahc.workspace = true util.workspace = true diff --git a/crates/isahc_http_client/LICENSE-APACHE b/crates/isahc_http_client/LICENSE-APACHE new file mode 120000 index 0000000000000..1cd601d0a3aff --- /dev/null +++ b/crates/isahc_http_client/LICENSE-APACHE @@ -0,0 +1 @@ +../../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 new file mode 100644 index 0000000000000..778f6a0459890 --- /dev/null +++ b/crates/isahc_http_client/src/isahc_http_client.rs @@ -0,0 +1,105 @@ +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 4b4b5e13dad43..bad4c5a05f475 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.workspace = true +reqwest = "0.11" serde.workspace = true [build-dependencies] diff --git a/crates/reqwest_client/Cargo.toml b/crates/reqwest_client/Cargo.toml deleted file mode 100644 index 060a382d72ee4..0000000000000 --- a/crates/reqwest_client/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[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 -tokio.workspace = true - -reqwest = { workspace = true, features = ["rustls-tls-manual-roots", "stream"] } diff --git a/crates/reqwest_client/LICENSE-GPL b/crates/reqwest_client/LICENSE-GPL deleted file mode 120000 index 89e542f750cd3..0000000000000 --- a/crates/reqwest_client/LICENSE-GPL +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-GPL \ No newline at end of file diff --git a/crates/reqwest_client/examples/client.rs b/crates/reqwest_client/examples/client.rs deleted file mode 100644 index 1f50d21e4edc2..0000000000000 --- a/crates/reqwest_client/examples/client.rs +++ /dev/null @@ -1,16 +0,0 @@ -use futures::AsyncReadExt as _; -use http_client::AsyncBody; -use http_client::HttpClient; -use reqwest_client::ReqwestClient; - -#[tokio::main] -async fn main() { - let resp = ReqwestClient::new() - .get("http://zed.dev", AsyncBody::empty(), true) - .await - .unwrap(); - - let mut body = String::new(); - resp.into_body().read_to_string(&mut body).await.unwrap(); - println!("{}", &body); -} diff --git a/crates/reqwest_client/src/reqwest_client.rs b/crates/reqwest_client/src/reqwest_client.rs deleted file mode 100644 index f8698b908096b..0000000000000 --- a/crates/reqwest_client/src/reqwest_client.rs +++ /dev/null @@ -1,259 +0,0 @@ -use std::{any::type_name, borrow::Cow, io::Read, pin::Pin, task::Poll}; - -use anyhow::anyhow; -use bytes::{BufMut, Bytes, BytesMut}; -use futures::{AsyncRead, TryStreamExt}; -use http_client::{http, AsyncBody, ReadTimeout}; -use reqwest::header::{HeaderMap, HeaderValue}; -use smol::future::FutureExt; - -const DEFAULT_CAPACITY: usize = 4096; - -pub struct ReqwestClient { - client: reqwest::Client, -} - -impl ReqwestClient { - pub fn new() -> Self { - Self { - client: reqwest::Client::new(), - } - } - - pub fn user_agent(agent: &str) -> anyhow::Result { - let mut map = HeaderMap::new(); - map.insert(http::header::USER_AGENT, HeaderValue::from_str(agent)?); - Ok(Self { - client: reqwest::Client::builder().default_headers(map).build()?, - }) - } -} - -impl From for ReqwestClient { - fn from(client: reqwest::Client) -> Self { - Self { client } - } -} - -// 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 ReaderStream { - reader: Option>>, - buf: BytesMut, - capacity: usize, -} - -impl ReaderStream { - fn new(reader: Pin>) -> Self { - Self { - reader: Some(reader), - buf: BytesMut::new(), - capacity: DEFAULT_CAPACITY, - } - } -} - -impl futures::Stream for ReaderStream { - 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)) -} - -enum WrappedBodyInner { - None, - SyncReader(std::io::Cursor>), - Stream(ReaderStream), -} - -struct WrappedBody(WrappedBodyInner); - -impl WrappedBody { - fn new(body: AsyncBody) -> Self { - match body.0 { - http_client::Inner::Empty => Self(WrappedBodyInner::None), - http_client::Inner::SyncReader(cursor) => Self(WrappedBodyInner::SyncReader(cursor)), - http_client::Inner::AsyncReader(pin) => { - Self(WrappedBodyInner::Stream(ReaderStream::new(pin))) - } - } - } -} - -impl futures::stream::Stream for WrappedBody { - type Item = Result; - - fn poll_next( - mut self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - match &mut self.0 { - WrappedBodyInner::None => Poll::Ready(None), - WrappedBodyInner::SyncReader(cursor) => { - let mut buf = Vec::new(); - match cursor.read_to_end(&mut buf) { - Ok(bytes) => { - if bytes == 0 { - return Poll::Ready(None); - } else { - return Poll::Ready(Some(Ok(Bytes::from(buf)))); - } - } - Err(e) => return Poll::Ready(Some(Err(e))), - } - } - WrappedBodyInner::Stream(stream) => { - // SAFETY: Pin projection - let stream = unsafe { Pin::new_unchecked(stream) }; - futures::Stream::poll_next(stream, cx) - } - } - } -} - -impl http_client::HttpClient for ReqwestClient { - fn proxy(&self) -> Option<&http::Uri> { - None - } - - 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 { - http_client::RedirectPolicy::NoFollow => reqwest::redirect::Policy::none(), - http_client::RedirectPolicy::FollowLimit(limit) => { - reqwest::redirect::Policy::limited(*limit as usize) - } - http_client::RedirectPolicy::FollowAll => reqwest::redirect::Policy::limited(100), - }); - } - - if let Some(ReadTimeout(timeout)) = parts.extensions.get::() { - request = request.timeout(*timeout); - } - - let body = WrappedBody::new(body); - let request = request.body(reqwest::Body::wrap_stream(body)); - - async move { - let response = request.send().await.map_err(|e| anyhow!(e))?; - let status = response.status(); - let mut builder = http::Response::builder().status(status.as_u16()); - for (name, value) in response.headers() { - builder = builder.header(name, value); - } - let bytes = response.bytes_stream(); - let bytes = bytes - .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() - } -} - -#[cfg(test)] -mod test { - - use core::str; - - use http_client::AsyncBody; - use smol::stream::StreamExt; - - use crate::WrappedBody; - - #[tokio::test] - async fn test_sync_streaming_upload() { - let mut body = WrappedBody::new(AsyncBody::from("hello there".to_string())).fuse(); - let result = body.next().await.unwrap().unwrap(); - assert!(body.next().await.is_none()); - assert_eq!(str::from_utf8(&result).unwrap(), "hello there"); - } -} diff --git a/crates/semantic_index/Cargo.toml b/crates/semantic_index/Cargo.toml index 508e64ffea362..f157cc9b3fc8e 100644 --- a/crates/semantic_index/Cargo.toml +++ b/crates/semantic_index/Cargo.toml @@ -51,6 +51,7 @@ 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"] } @@ -61,7 +62,6 @@ language = { workspace = true, features = ["test-support"] } languages.workspace = true project = { workspace = true, features = ["test-support"] } tempfile.workspace = true -ureq_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 1ebed4c17f3bd..c5c2c633a1060 100644 --- a/crates/semantic_index/examples/index.rs +++ b/crates/semantic_index/examples/index.rs @@ -2,6 +2,7 @@ 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}; @@ -28,11 +29,7 @@ fn main() { let clock = Arc::new(FakeSystemClock::default()); let http = Arc::new(HttpClientWithUrl::new( - Arc::new(ureq_client::UreqClient::new( - None, - "Zed semantic index example".to_string(), - cx.background_executor().clone(), - )), + IsahcHttpClient::new(None, None), "http://localhost:11434", None, )); diff --git a/crates/storybook/Cargo.toml b/crates/storybook/Cargo.toml index b05c7692f9529..f8e78acad336b 100644 --- a/crates/storybook/Cargo.toml +++ b/crates/storybook/Cargo.toml @@ -22,6 +22,7 @@ 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 @@ -35,7 +36,6 @@ strum = { workspace = true, features = ["derive"] } theme.workspace = true title_bar = { workspace = true, features = ["stories"] } ui = { workspace = true, features = ["stories"] } -ureq_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 a77602efcca8b..73b1396da5166 100644 --- a/crates/storybook/src/storybook.rs +++ b/crates/storybook/src/storybook.rs @@ -4,14 +4,13 @@ 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 settings::{KeymapFile, Settings}; @@ -19,7 +18,6 @@ use simplelog::SimpleLogger; use strum::IntoEnumIterator; use theme::{ThemeRegistry, ThemeSettings}; use ui::prelude::*; -use ureq_client::UreqClient; use crate::app_menus::app_menus; use crate::assets::Assets; @@ -68,12 +66,8 @@ fn main() { gpui::App::new().with_assets(Assets).run(move |cx| { load_embedded_fonts(cx).unwrap(); - let http_client = UreqClient::new( - None, - "zed_storybook".to_string(), - cx.background_executor().clone(), - ); - cx.set_http_client(Arc::new(http_client)); + let http_client = IsahcHttpClient::new(None, Some("zed_storybook".to_string())); + cx.set_http_client(http_client); settings::init(cx); theme::init(theme::LoadThemes::All(Box::new(Assets)), cx); diff --git a/crates/ureq_client/LICENSE-GPL b/crates/ureq_client/LICENSE-GPL deleted file mode 120000 index 89e542f750cd3..0000000000000 --- a/crates/ureq_client/LICENSE-GPL +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-GPL \ No newline at end of file diff --git a/crates/ureq_client/examples/client.rs b/crates/ureq_client/examples/client.rs deleted file mode 100644 index c5caae40dac9e..0000000000000 --- a/crates/ureq_client/examples/client.rs +++ /dev/null @@ -1,24 +0,0 @@ -use futures::AsyncReadExt; -use http_client::{AsyncBody, HttpClient}; -use ureq_client::UreqClient; - -fn main() { - gpui::App::headless().run(|cx| { - println!("{:?}", std::thread::current().id()); - cx.spawn(|cx| async move { - let resp = UreqClient::new( - None, - "Conrad's bot".to_string(), - cx.background_executor().clone(), - ) - .get("http://zed.dev", AsyncBody::empty(), true) - .await - .unwrap(); - - let mut body = String::new(); - resp.into_body().read_to_string(&mut body).await.unwrap(); - println!("{}", body); - }) - .detach(); - }) -} diff --git a/crates/ureq_client/src/ureq_client.rs b/crates/ureq_client/src/ureq_client.rs deleted file mode 100644 index d3d8d3aedc502..0000000000000 --- a/crates/ureq_client/src/ureq_client.rs +++ /dev/null @@ -1,200 +0,0 @@ -use std::any::type_name; -use std::collections::HashMap; -use std::io::Read; -use std::sync::Arc; -use std::time::Duration; -use std::{pin::Pin, task::Poll}; - -use anyhow::Error; -use futures::channel::mpsc; -use futures::future::BoxFuture; -use futures::{AsyncRead, SinkExt, StreamExt}; -use http_client::{http, AsyncBody, HttpClient, RedirectPolicy, Uri}; -use smol::future::FutureExt; -use util::ResultExt; - -pub struct UreqClient { - // Note in ureq 2.x the options are stored on the Agent. - // In ureq 3.x we'll be able to set these on the request. - // In practice it's probably "fine" to have many clients, the number of distinct options - // is low; and most requests to the same connection will have the same options so the - // connection pool will work. - clients: Arc>>, - proxy_url: Option, - proxy: Option, - user_agent: String, - background_executor: gpui::BackgroundExecutor, -} - -impl UreqClient { - pub fn new( - proxy_url: Option, - user_agent: String, - background_executor: gpui::BackgroundExecutor, - ) -> Self { - Self { - clients: Arc::default(), - proxy_url: proxy_url.clone(), - proxy: proxy_url.and_then(|url| ureq::Proxy::new(url.to_string()).log_err()), - user_agent, - background_executor, - } - } - - fn agent_for(&self, redirect_policy: RedirectPolicy, timeout: Duration) -> ureq::Agent { - let mut clients = self.clients.lock(); - // in case our assumption of distinct options is wrong, we'll sporadically clean it out. - if clients.len() > 50 { - clients.clear() - } - - clients - .entry((timeout, redirect_policy.clone())) - .or_insert_with(|| { - let mut builder = ureq::AgentBuilder::new() - .timeout_connect(Duration::from_secs(5)) - .timeout_read(timeout) - .timeout_write(timeout) - .user_agent(&self.user_agent) - .tls_config(http_client::TLS_CONFIG.clone()) - .redirects(match redirect_policy { - RedirectPolicy::NoFollow => 0, - RedirectPolicy::FollowLimit(limit) => limit, - RedirectPolicy::FollowAll => 100, - }); - if let Some(proxy) = &self.proxy { - builder = builder.proxy(proxy.clone()); - } - builder.build() - }) - .clone() - } -} -impl HttpClient for UreqClient { - fn proxy(&self) -> Option<&Uri> { - self.proxy_url.as_ref() - } - - fn type_name(&self) -> &'static str { - type_name::() - } - - fn send( - &self, - request: http::Request, - ) -> BoxFuture<'static, Result, Error>> { - let agent = self.agent_for( - request - .extensions() - .get::() - .cloned() - .unwrap_or_default(), - request - .extensions() - .get::() - .cloned() - .unwrap_or_default() - .0, - ); - let mut req = agent.request(&request.method().as_ref(), &request.uri().to_string()); - for (name, value) in request.headers().into_iter() { - req = req.set(name.as_str(), value.to_str().unwrap()); - } - let body = request.into_body(); - let executor = self.background_executor.clone(); - - self.background_executor - .spawn(async move { - let response = match req.send(body) { - Ok(response) => response, - Err(e) => match e { - ureq::Error::Status(_, response) => response, - ureq::Error::Transport(transport) => { - anyhow::bail!(transport) - } - }, - }; - - let mut builder = http::Response::builder() - .status(response.status()) - .version(http::Version::HTTP_11); - for name in response.headers_names() { - if let Some(value) = response.header(&name) { - builder = builder.header(name, value); - } - } - - let body = AsyncBody::from_reader(UreqResponseReader::new(executor, response)); - let http_response = builder.body(body)?; - - Ok(http_response) - }) - .boxed() - } -} - -struct UreqResponseReader { - receiver: mpsc::Receiver>>, - buffer: Vec, - idx: usize, - _task: gpui::Task<()>, -} - -impl UreqResponseReader { - fn new(background_executor: gpui::BackgroundExecutor, response: ureq::Response) -> Self { - let (mut sender, receiver) = mpsc::channel(1); - let mut reader = response.into_reader(); - let task = background_executor.spawn(async move { - let mut buffer = vec![0; 8192]; - loop { - let n = match reader.read(&mut buffer) { - Ok(0) => break, - Ok(n) => n, - Err(e) => { - let _ = sender.send(Err(e)).await; - break; - } - }; - let _ = sender.send(Ok(buffer[..n].to_vec())).await; - } - }); - - UreqResponseReader { - _task: task, - receiver, - buffer: Vec::new(), - idx: 0, - } - } -} - -impl AsyncRead for UreqResponseReader { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &mut [u8], - ) -> Poll> { - if self.buffer.is_empty() { - match self.receiver.poll_next_unpin(cx) { - Poll::Ready(Some(Ok(data))) => self.buffer = data, - Poll::Ready(Some(Err(e))) => { - return Poll::Ready(Err(e)); - } - Poll::Ready(None) => { - return Poll::Ready(Ok(0)); - } - Poll::Pending => { - return Poll::Pending; - } - } - } - let n = std::cmp::min(buf.len(), self.buffer.len() - self.idx); - buf[..n].copy_from_slice(&self.buffer[self.idx..self.idx + n]); - self.idx += n; - if self.idx == self.buffer.len() { - self.buffer.clear(); - self.idx = 0; - } - Poll::Ready(Ok(n)) - } -} diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index bb347f49b79d8..410371cb0c554 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 = { workspace = true, "optional" = true } +async-compat = { version = "0.2.1", "optional" = true } async-trait = { workspace = true, "optional" = true } collections.workspace = true command_palette.workspace = true diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index e340e176a7414..e22f75f5bb3e5 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -57,6 +57,7 @@ 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 @@ -107,7 +108,6 @@ theme.workspace = true theme_selector.workspace = true time.workspace = true ui.workspace = true -ureq_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 535cafbccba66..9857c60491b1c 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 ureq_client::UreqClient; use assets::Assets; use node_runtime::{NodeBinaryOptions, NodeRuntime}; @@ -334,7 +334,9 @@ fn main() { log::info!("========== starting zed =========="); - let app = App::new().with_assets(Assets); + let app = App::new() + .with_assets(Assets) + .with_http_client(IsahcHttpClient::new(None, None)); let system_id = app.background_executor().block(system_id()).ok(); let installation_id = app.background_executor().block(installation_id()).ok(); @@ -468,8 +470,8 @@ fn main() { .ok() }) .or_else(read_proxy_from_env); - let http = UreqClient::new(proxy_url, user_agent, cx.background_executor().clone()); - cx.set_http_client(Arc::new(http)); + let http = IsahcHttpClient::new(proxy_url, Some(user_agent)); + cx.set_http_client(http); ::set_global(fs.clone(), cx);