Detailed changes
@@ -846,8 +846,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",
@@ -880,15 +880,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",
]
@@ -905,9 +904,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",
@@ -915,7 +914,7 @@ dependencies = [
"futures-util",
"log",
"pin-project-lite",
- "tungstenite 0.20.1",
+ "tungstenite 0.24.0",
]
[[package]]
@@ -1064,7 +1063,7 @@ dependencies = [
"fastrand 2.1.1",
"hex",
"http 0.2.12",
- "ring 0.17.8",
+ "ring",
"time",
"tokio",
"tracing",
@@ -1233,7 +1232,7 @@ dependencies = [
"once_cell",
"p256",
"percent-encoding",
- "ring 0.17.8",
+ "ring",
"sha2",
"subtle",
"time",
@@ -1336,13 +1335,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",
@@ -1432,7 +1431,7 @@ dependencies = [
"headers",
"http 0.2.12",
"http-body 0.4.6",
- "hyper",
+ "hyper 0.14.30",
"itoa",
"matchit",
"memchr",
@@ -1445,7 +1444,7 @@ dependencies = [
"serde_path_to_error",
"serde_urlencoded",
"sha1",
- "sync_wrapper",
+ "sync_wrapper 0.1.2",
"tokio",
"tokio-tungstenite 0.20.1",
"tower",
@@ -1584,7 +1583,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"shlex",
"syn 2.0.76",
]
@@ -1604,7 +1603,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"shlex",
"syn 2.0.76",
]
@@ -2100,12 +2099,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"
@@ -2363,8 +2356,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",
@@ -2402,6 +2395,7 @@ dependencies = [
"anyhow",
"async-native-tls",
"async-recursion 0.3.2",
+ "async-tls",
"async-tungstenite",
"chrono",
"clock",
@@ -2419,8 +2413,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 +2559,8 @@ dependencies = [
"headless",
"hex",
"http_client",
- "hyper",
+ "hyper 0.14.30",
"indoc",
- "isahc_http_client",
"jsonwebtoken",
"language",
"language_model",
@@ -2593,7 +2584,8 @@ dependencies = [
"release_channel",
"remote",
"remote_server",
- "reqwest",
+ "reqwest 0.11.27",
+ "reqwest_client",
"rpc",
"rustc-demangle",
"scrypt",
@@ -2677,7 +2669,7 @@ dependencies = [
name = "collections"
version = "0.1.0"
dependencies = [
- "rustc-hash",
+ "rustc-hash 1.1.0",
]
[[package]]
@@ -2995,7 +2987,7 @@ dependencies = [
"log",
"rangemap",
"rayon",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"rustybuzz",
"self_cell",
"swash",
@@ -3085,7 +3077,7 @@ dependencies = [
"hashbrown 0.14.5",
"log",
"regalloc2",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"smallvec",
"target-lexicon",
]
@@ -3341,36 +3333,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,7 +3994,6 @@ dependencies = [
"git",
"gpui",
"http_client",
- "isahc_http_client",
"language",
"languages",
"node_runtime",
@@ -4043,6 +4004,7 @@ dependencies = [
"serde_json",
"settings",
"smol",
+ "ureq_client",
]
[[package]]
@@ -4127,7 +4089,6 @@ dependencies = [
"gpui",
"http_client",
"indexed_docs",
- "isahc_http_client",
"language",
"log",
"lsp",
@@ -4136,6 +4097,7 @@ dependencies = [
"paths",
"project",
"release_channel",
+ "reqwest_client",
"schemars",
"semantic_version",
"serde",
@@ -4145,8 +4107,10 @@ dependencies = [
"snippet_provider",
"task",
"theme",
+ "tokio",
"toml 0.8.19",
"ui",
+ "ureq_client",
"url",
"util",
"wasm-encoder 0.215.0",
@@ -4166,9 +4130,9 @@ dependencies = [
"env_logger",
"extension",
"fs",
- "isahc_http_client",
"language",
"log",
+ "reqwest_client",
"rpc",
"serde",
"serde_json",
@@ -4415,7 +4379,7 @@ dependencies = [
"futures-core",
"futures-sink",
"nanorand",
- "spin 0.9.8",
+ "spin",
]
[[package]]
@@ -5181,6 +5145,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"
@@ -5561,8 +5544,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",
@@ -5603,7 +5588,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
- "h2",
+ "h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"httparse",
@@ -5617,6 +5602,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"
@@ -5625,12 +5630,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]]
@@ -5640,12 +5662,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"
@@ -6013,44 +6070,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"
@@ -6155,7 +6174,7 @@ dependencies = [
"base64 0.21.7",
"js-sys",
"pem",
- "ring 0.17.8",
+ "ring",
"serde",
"serde_json",
"simple_asn1",
@@ -6406,7 +6425,7 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
- "spin 0.9.8",
+ "spin",
]
[[package]]
@@ -6601,7 +6620,7 @@ dependencies = [
"prost",
"prost-build",
"prost-types",
- "reqwest",
+ "reqwest 0.12.8",
"serde",
]
@@ -7085,7 +7104,7 @@ dependencies = [
"hexf-parse",
"indexmap 2.4.0",
"log",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"spirv",
"termcolor",
"thiserror",
@@ -8742,6 +8761,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"
@@ -9019,7 +9086,7 @@ checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6"
dependencies = [
"hashbrown 0.13.2",
"log",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"slice-group-by",
"smallvec",
]
@@ -9196,11 +9263,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",
@@ -9213,8 +9280,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",
@@ -9225,6 +9292,68 @@ 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"
@@ -9273,21 +9402,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"
@@ -9298,8 +9412,8 @@ dependencies = [
"cfg-if",
"getrandom 0.2.15",
"libc",
- "spin 0.9.8",
- "untrusted 0.9.0",
+ "spin",
+ "untrusted",
"windows-sys 0.52.0",
]
@@ -9455,7 +9569,7 @@ dependencies = [
"futures 0.3.30",
"glob",
"rand 0.8.5",
- "ring 0.17.8",
+ "ring",
"serde",
"serde_json",
"shellexpand 3.1.0",
@@ -9527,6 +9641,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"
@@ -9578,26 +9698,28 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.20.9"
+version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
+checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
dependencies = [
"log",
- "ring 0.16.20",
+ "ring",
+ "rustls-webpki 0.101.7",
"sct",
- "webpki",
]
[[package]]
name = "rustls"
-version = "0.21.12"
+version = "0.23.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
+checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
dependencies = [
- "log",
- "ring 0.17.8",
- "rustls-webpki",
- "sct",
+ "once_cell",
+ "ring",
+ "rustls-pki-types",
+ "rustls-webpki 0.102.8",
+ "subtle",
+ "zeroize",
]
[[package]]
@@ -9656,8 +9778,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]]
@@ -9771,8 +9904,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]]
@@ -9968,7 +10101,6 @@ dependencies = [
"gpui",
"heed",
"http_client",
- "isahc_http_client",
"language",
"language_model",
"languages",
@@ -9986,6 +10118,7 @@ dependencies = [
"tree-sitter",
"ui",
"unindent",
+ "ureq_client",
"util",
"workspace",
"worktree",
@@ -10418,17 +10551,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"
@@ -10543,12 +10665,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"
@@ -11178,6 +11294,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"
@@ -11218,7 +11343,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]]
@@ -11231,6 +11367,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"
@@ -11607,7 +11753,7 @@ dependencies = [
"fancy-regex",
"lazy_static",
"parking_lot",
- "rustc-hash",
+ "rustc-hash 1.1.0",
]
[[package]]
@@ -11822,6 +11968,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"
@@ -11871,9 +12028,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",
@@ -12055,16 +12212,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"
@@ -12371,6 +12518,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"
@@ -7,6 +7,7 @@ members = [
"crates/assistant",
"crates/assistant_slash_command",
"crates/assistant_tool",
+ "crates/ureq_client",
"crates/audio",
"crates/auto_update",
"crates/breadcrumbs",
@@ -52,7 +53,6 @@ members = [
"crates/indexed_docs",
"crates/inline_completion_button",
"crates/install_cli",
- "crates/isahc_http_client",
"crates/journal",
"crates/language",
"crates/language_model",
@@ -87,6 +87,7 @@ members = [
"crates/release_channel",
"crates/remote",
"crates/remote_server",
+ "crates/reqwest_client",
"crates/repl",
"crates/rich_text",
"crates/rope",
@@ -186,6 +187,8 @@ assets = { path = "crates/assets" }
assistant = { path = "crates/assistant" }
assistant_slash_command = { path = "crates/assistant_slash_command" }
assistant_tool = { path = "crates/assistant_tool" }
+ureq_client = { path = "crates/ureq_client" }
+async-compat = { version = "0.2.1" }
audio = { path = "crates/audio" }
auto_update = { path = "crates/auto_update" }
breadcrumbs = { path = "crates/breadcrumbs" }
@@ -228,7 +231,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 +267,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" }
@@ -325,7 +328,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"
@@ -364,10 +367,7 @@ 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"
@@ -392,13 +392,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"
@@ -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
@@ -1023,7 +1023,7 @@ impl Client {
&self,
http: Arc<HttpClientWithUrl>,
release_channel: Option<ReleaseChannel>,
- ) -> impl Future<Output = Result<Url>> {
+ ) -> impl Future<Output = Result<url::Url>> {
#[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::<Vec<_>>(),
- );
- 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(
@@ -37,7 +37,7 @@ futures.workspace = true
google_ai.workspace = true
hex.workspace = true
http_client.workspace = true
-isahc_http_client.workspace = true
+reqwest_client.workspace = true
jsonwebtoken.workspace = true
live_kit_server.workspace = true
log.workspace = true
@@ -674,7 +674,7 @@ pub struct EditorEventRow {
copilot_enabled_for_language: bool,
historical_event: bool,
architecture: String,
- is_staff: Option<bool>,
+ is_staff: bool,
major: Option<i32>,
minor: Option<i32>,
patch: Option<i32>,
@@ -708,7 +708,7 @@ impl EditorEventRow {
installation_id: body.installation_id.clone().unwrap_or_default(),
session_id: body.session_id.clone(),
metrics_id: body.metrics_id.clone().unwrap_or_default(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
operation: event.operation,
file_extension: event.file_extension.unwrap_or_default(),
@@ -741,7 +741,7 @@ pub struct InlineCompletionEventRow {
region_code: String,
city: String,
time: i64,
- is_staff: Option<bool>,
+ is_staff: bool,
major: Option<i32>,
minor: Option<i32>,
patch: Option<i32>,
@@ -772,7 +772,7 @@ impl InlineCompletionEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone().unwrap_or_default(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
file_extension: event.file_extension.unwrap_or_default(),
signed_in: wrapper.signed_in,
@@ -800,7 +800,7 @@ pub struct CallEventRow {
// ClientEventBase
installation_id: String,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// CallEventRow
@@ -832,7 +832,7 @@ impl CallEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone().unwrap_or_default(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
operation: event.operation,
room_id: event.room_id,
@@ -856,7 +856,7 @@ pub struct AssistantEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// AssistantEventRow
@@ -891,7 +891,7 @@ impl AssistantEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
conversation_id: event.conversation_id.unwrap_or_default(),
kind: event.kind.to_string(),
@@ -909,7 +909,7 @@ impl AssistantEventRow {
pub struct CpuEventRow {
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
usage_as_percentage: f32,
core_count: u32,
app_version: String,
@@ -947,7 +947,7 @@ impl CpuEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
usage_as_percentage: event.usage_as_percentage,
core_count: event.core_count,
@@ -970,7 +970,7 @@ pub struct MemoryEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// MemoryEventRow
@@ -1001,7 +1001,7 @@ impl MemoryEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
memory_in_bytes: event.memory_in_bytes,
virtual_memory_in_bytes: event.virtual_memory_in_bytes,
@@ -1024,7 +1024,7 @@ pub struct AppEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// AppEventRow
@@ -1054,7 +1054,7 @@ impl AppEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
operation: event.operation,
}
@@ -1076,7 +1076,7 @@ pub struct SettingEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// SettingEventRow
setting: String,
@@ -1106,7 +1106,7 @@ impl SettingEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
setting: event.setting,
value: event.value,
@@ -1129,7 +1129,7 @@ pub struct ExtensionEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// ExtensionEventRow
@@ -1164,7 +1164,7 @@ impl ExtensionEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
extension_id: event.extension_id,
extension_version: event.version,
@@ -1198,7 +1198,7 @@ pub struct ReplEventRow {
// ClientEventBase
installation_id: Option<String>,
session_id: Option<String>,
- is_staff: Option<bool>,
+ is_staff: bool,
time: i64,
// ReplEventRow
@@ -1230,7 +1230,7 @@ impl ReplEventRow {
os_version: body.os_version.clone().unwrap_or_default(),
installation_id: body.installation_id.clone(),
session_id: body.session_id.clone(),
- is_staff: body.is_staff,
+ is_staff: body.is_staff.unwrap_or_default(),
time: time.timestamp_millis(),
kernel_language: event.kernel_language,
kernel_status: event.kernel_status,
@@ -22,7 +22,8 @@ use chrono::{DateTime, Duration, Utc};
use collections::HashMap;
use db::{usage_measure::UsageMeasure, ActiveUserCount, LlmDatabase};
use futures::{Stream, StreamExt as _};
-use isahc_http_client::IsahcHttpClient;
+
+use reqwest_client::ReqwestClient;
use rpc::ListModelsResponse;
use rpc::{
proto::Plan, LanguageModelProvider, PerformCompletionParams, EXPIRED_LLM_TOKEN_HEADER_NAME,
@@ -43,7 +44,7 @@ pub struct LlmState {
pub config: Config,
pub executor: Executor,
pub db: Arc<LlmDatabase>,
- pub http_client: IsahcHttpClient,
+ pub http_client: ReqwestClient,
pub clickhouse_client: Option<clickhouse::Client>,
active_user_count_by_model:
RwLock<HashMap<(LanguageModelProvider, String), (DateTime<Utc>, ActiveUserCount)>>,
@@ -69,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,
@@ -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};
@@ -954,8 +954,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;
@@ -16,6 +16,7 @@ path = "src/eval.rs"
[dependencies]
clap.workspace = true
anyhow.workspace = true
+ureq_client.workspace = true
client.workspace = true
clock.workspace = true
collections.workspace = true
@@ -24,7 +25,6 @@ feature_flags.workspace = true
fs.workspace = true
git.workspace = true
gpui.workspace = true
-isahc_http_client.workspace = true
language.workspace = true
languages.workspace = true
http_client.workspace = true
@@ -32,6 +32,7 @@ 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";
@@ -100,7 +101,11 @@ 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(UreqClient::new(
+ None,
+ "Zed LLM evals".to_string(),
+ executor.clone(),
+ ));
cx.set_http_client(client.clone());
match cli.command {
Commands::Fetch {} => {
@@ -56,10 +56,12 @@ task.workspace = true
serde_json_lenient.workspace = true
[dev-dependencies]
-isahc_http_client.workspace = true
+ureq_client.workspace = true
ctor.workspace = true
env_logger.workspace = true
parking_lot.workspace = true
+reqwest_client.workspace = true
+tokio.workspace = true
fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
@@ -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";
-const WASI_ADAPTER_URL: &str =
+pub 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
@@ -1,3 +1,4 @@
+use crate::extension_builder::WASI_ADAPTER_URL;
use crate::extension_manifest::SchemaVersion;
use crate::extension_settings::ExtensionSettings;
use crate::{
@@ -11,14 +12,14 @@ use collections::BTreeMap;
use fs::{FakeFs, Fs, RealFs};
use futures::{io::BufReader, AsyncReadExt, StreamExt};
use gpui::{Context, SemanticVersion, TestAppContext};
-use http_client::{FakeHttpClient, Response};
+use http_client::{AsyncBody, FakeHttpClient, HttpClient, 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;
@@ -28,6 +29,7 @@ use std::{
sync::Arc,
};
use theme::ThemeRegistry;
+use ureq_client::UreqClient;
use util::test::temp_tree;
#[cfg(test)]
@@ -576,7 +578,7 @@ 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(UreqClient::new(None, user_agent, cx.executor().clone()));
let extension_store = cx.new_model(|cx| {
ExtensionStore::new(
@@ -769,6 +771,50 @@ 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);
@@ -18,7 +18,7 @@ clap = { workspace = true, features = ["derive"] }
env_logger.workspace = true
extension = { workspace = true, features = ["no-webrtc"] }
fs.workspace = true
-isahc_http_client.workspace = true
+reqwest_client.workspace = true
language.workspace = true
log.workspace = true
rpc.workspace = true
@@ -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
@@ -16,7 +16,9 @@ path = "src/http_client.rs"
doctest = true
[dependencies]
-http = "0.2"
+http = "1.1"
+rustls.workspace = true
+rustls-native-certs.workspace = true
anyhow.workspace = true
derive_more.workspace = true
futures.workspace = true
@@ -11,13 +11,21 @@ use http::request::Builder;
#[cfg(feature = "test-support")]
use std::fmt;
use std::{
- sync::{Arc, Mutex},
+ 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 +34,23 @@ pub enum RedirectPolicy {
}
pub struct FollowRedirects(pub bool);
+pub static TLS_CONFIG: LazyLock<Arc<rustls::ClientConfig>> = 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.
@@ -1 +0,0 @@
-../../LICENSE-APACHE
@@ -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<Uri>, user_agent: Option<String>) -> Arc<IsahcHttpClient> {
- 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<isahc::HttpClient> 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<http_client::AsyncBody>,
- ) -> BoxFuture<'static, Result<http_client::Response<http_client::AsyncBody>, anyhow::Error>>
- {
- let redirect_policy = req
- .extensions()
- .get::<http_client::RedirectPolicy>()
- .cloned()
- .unwrap_or_default();
- let read_timeout = req
- .extensions()
- .get::<http_client::ReadTimeout>()
- .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")),
- }
- })
- }
-}
@@ -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]
@@ -0,0 +1,31 @@
+[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
+futures.workspace = true
+serde.workspace = true
+smol.workspace = true
+http_client.workspace = true
+tokio.workspace = true
+bytes = "1.0"
+
+reqwest = { workspace = true, features = ["rustls-tls-manual-roots", "stream"] }
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,16 @@
+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);
+}
@@ -0,0 +1,232 @@
+use std::{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<Self> {
+ 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<reqwest::Client> 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<Pin<Box<dyn futures::AsyncRead + Send + Sync>>>,
+ buf: BytesMut,
+ capacity: usize,
+}
+
+impl ReaderStream {
+ fn new(reader: Pin<Box<dyn futures::AsyncRead + Send + Sync>>) -> Self {
+ Self {
+ reader: Some(reader),
+ buf: BytesMut::new(),
+ capacity: DEFAULT_CAPACITY,
+ }
+ }
+}
+
+impl futures::Stream for ReaderStream {
+ type Item = std::io::Result<Bytes>;
+
+ fn poll_next(
+ mut self: Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> Poll<Option<Self::Item>> {
+ 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<Box<dyn futures::AsyncRead + Send + Sync>>,
+ cx: &mut std::task::Context<'_>,
+ buf: &mut BytesMut,
+) -> Poll<std::io::Result<usize>> {
+ 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<u8>]`.
+ let dst = unsafe { &mut *(dst as *mut _ as *mut [std::mem::MaybeUninit<u8>]) };
+ 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<Cow<'static, [u8]>>),
+ 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<Bytes, std::io::Error>;
+
+ fn poll_next(
+ mut self: std::pin::Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Option<Self::Item>> {
+ 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(_) => {
+ 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 send(
+ &self,
+ req: http::Request<http_client::AsyncBody>,
+ ) -> futures::future::BoxFuture<
+ 'static,
+ Result<http_client::Response<http_client::AsyncBody>, 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::<http_client::RedirectPolicy>() {
+ 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::<ReadTimeout>() {
+ 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()
+ }
+}
@@ -51,7 +51,7 @@ workspace.workspace = true
worktree.workspace = true
[dev-dependencies]
-isahc_http_client.workspace = true
+ureq_client.workspace = true
env_logger.workspace = true
client = { workspace = true, features = ["test-support"] }
fs = { workspace = true, features = ["test-support"] }
@@ -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,11 @@ fn main() {
let clock = Arc::new(FakeSystemClock::default());
let http = Arc::new(HttpClientWithUrl::new(
- IsahcHttpClient::new(None, None),
+ Arc::new(ureq_client::UreqClient::new(
+ None,
+ "Zed semantic index example".to_string(),
+ cx.background_executor().clone(),
+ )),
"http://localhost:11434",
None,
));
@@ -1,5 +1,5 @@
[package]
-name = "isahc_http_client"
+name = "ureq_client"
version = "0.1.0"
edition = "2021"
publish = false
@@ -12,11 +12,21 @@ workspace = true
test-support = []
[lib]
-path = "src/isahc_http_client.rs"
+path = "src/ureq_client.rs"
+doctest = true
+
+[[example]]
+name = "client"
+path = "examples/client.rs"
[dependencies]
anyhow.workspace = true
futures.workspace = true
+serde.workspace = true
+smol.workspace = true
+gpui.workspace = true
http_client.workspace = true
-isahc.workspace = true
util.workspace = true
+parking_lot.workspace = true
+
+ureq = "=2.9.1"
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,24 @@
+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();
+ })
+}
@@ -0,0 +1,187 @@
+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<parking_lot::Mutex<HashMap<(Duration, RedirectPolicy), ureq::Agent>>>,
+ proxy_url: Option<Uri>,
+ proxy: Option<ureq::Proxy>,
+ user_agent: String,
+ background_executor: gpui::BackgroundExecutor,
+}
+
+impl UreqClient {
+ pub fn new(
+ proxy_url: Option<Uri>,
+ 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 send(
+ &self,
+ request: http::Request<AsyncBody>,
+ ) -> BoxFuture<'static, Result<http::Response<AsyncBody>, Error>> {
+ let agent = self.agent_for(
+ request
+ .extensions()
+ .get::<RedirectPolicy>()
+ .cloned()
+ .unwrap_or_default(),
+ request
+ .extensions()
+ .get::<http_client::ReadTimeout>()
+ .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 = req.send(body)?;
+
+ 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<std::io::Result<Vec<u8>>>,
+ buffer: Vec<u8>,
+ 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<std::io::Result<usize>> {
+ 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))
+ }
+}
@@ -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
@@ -57,7 +57,7 @@ http_client.workspace = true
image_viewer.workspace = true
inline_completion_button.workspace = true
install_cli.workspace = true
-isahc_http_client.workspace = true
+ureq_client.workspace = true
journal.workspace = true
language.workspace = true
language_model.workspace = true
@@ -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,9 +334,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();
@@ -470,8 +468,8 @@ 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 = UreqClient::new(proxy_url, user_agent, cx.background_executor().clone());
+ cx.set_http_client(Arc::new(http));
<dyn Fs>::set_global(fs.clone(), cx);