Compare commits

...

1 Commits

Author SHA1 Message Date
Conrad Irwin
bab228fc10 ureq 2024-09-25 16:36:51 -06:00
8 changed files with 489 additions and 22 deletions

256
Cargo.lock generated
View File

@@ -847,8 +847,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",
@@ -1085,6 +1085,33 @@ dependencies = [
"zeroize",
]
[[package]]
name = "aws-lc-rs"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f95446d919226d587817a7d21379e6eb099b97b45110a7f272a444ca5c54070"
dependencies = [
"aws-lc-sys",
"mirai-annotations",
"paste",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3ddc4a5b231dd6958b140ff3151b6412b3f4321fab354f399eec8f14b06df62"
dependencies = [
"bindgen 0.69.4",
"cc",
"cmake",
"dunce",
"fs_extra",
"libc",
"paste",
]
[[package]]
name = "aws-runtime"
version = "1.4.2"
@@ -1337,13 +1364,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",
@@ -1433,7 +1460,7 @@ dependencies = [
"headers",
"http 0.2.12",
"http-body 0.4.6",
"hyper",
"hyper 0.14.30",
"itoa",
"matchit",
"memchr",
@@ -1582,12 +1609,15 @@ dependencies = [
"itertools 0.12.1",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.76",
"which 4.4.2",
]
[[package]]
@@ -2364,7 +2394,7 @@ dependencies = [
"clickhouse-derive",
"clickhouse-rs-cityhash-sys",
"futures 0.3.30",
"hyper",
"hyper 0.14.30",
"hyper-tls",
"lz4",
"sealed",
@@ -2452,6 +2482,15 @@ dependencies = [
"smallvec",
]
[[package]]
name = "cmake"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
dependencies = [
"cc",
]
[[package]]
name = "cobs"
version = "0.2.3"
@@ -2568,7 +2607,7 @@ dependencies = [
"headless",
"hex",
"http_client",
"hyper",
"hyper 1.4.1",
"indoc",
"isahc_http_client",
"jsonwebtoken",
@@ -3669,6 +3708,12 @@ dependencies = [
"phf",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "dwrote"
version = "0.11.1"
@@ -4596,6 +4641,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "fsevent"
version = "0.1.0"
@@ -5185,6 +5236,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"
@@ -5565,7 +5635,7 @@ dependencies = [
"anyhow",
"derive_more",
"futures 0.3.30",
"http 0.2.12",
"http 1.1.0",
"log",
"serde",
"serde_json",
@@ -5607,7 +5677,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
"h2",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"httparse",
@@ -5621,6 +5691,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"
@@ -5629,12 +5719,31 @@ 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",
"log",
"rustls 0.23.13",
"rustls-native-certs 0.8.0",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.0",
"tower-service",
]
[[package]]
@@ -5644,12 +5753,51 @@ 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-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 = "hyper_client"
version = "0.1.0"
dependencies = [
"anyhow",
"derive_more",
"futures 0.3.30",
"gpui",
"http_client",
"hyper 1.4.1",
"hyper-rustls 0.27.3",
"hyper-util",
"log",
"serde",
"serde_json",
"smol",
"ureq",
"url",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
@@ -6478,7 +6626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.48.5",
"windows-targets 0.52.6",
]
[[package]]
@@ -7045,6 +7193,12 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "mirai-annotations"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
[[package]]
name = "multi_buffer"
version = "0.1.0"
@@ -9201,10 +9355,10 @@ dependencies = [
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"hyper",
"hyper 0.14.30",
"hyper-tls",
"ipnet",
"js-sys",
@@ -9601,10 +9755,26 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
dependencies = [
"log",
"ring 0.17.8",
"rustls-webpki",
"rustls-webpki 0.101.7",
"sct",
]
[[package]]
name = "rustls"
version = "0.23.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
dependencies = [
"aws-lc-rs",
"log",
"once_cell",
"ring 0.17.8",
"rustls-pki-types",
"rustls-webpki 0.102.8",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
@@ -9665,6 +9835,18 @@ dependencies = [
"untrusted 0.9.0",
]
[[package]]
name = "rustls-webpki"
version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"aws-lc-rs",
"ring 0.17.8",
"rustls-pki-types",
"untrusted 0.9.0",
]
[[package]]
name = "rustversion"
version = "1.0.17"
@@ -11813,6 +11995,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"
@@ -12532,6 +12725,22 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a"
dependencies = [
"base64 0.22.1",
"flate2",
"log",
"once_cell",
"rustls 0.23.13",
"rustls-pki-types",
"url",
"webpki-roots 0.26.6",
]
[[package]]
name = "url"
version = "2.5.2"
@@ -12835,7 +13044,7 @@ dependencies = [
"futures-util",
"headers",
"http 0.2.12",
"hyper",
"hyper 0.14.30",
"log",
"mime",
"mime_guess",
@@ -13405,6 +13614,15 @@ version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "webpki-roots"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "weezl"
version = "0.1.8"
@@ -13535,7 +13753,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.48.0",
"windows-sys 0.59.0",
]
[[package]]

View File

@@ -129,6 +129,7 @@ members = [
"crates/worktree",
"crates/zed",
"crates/zed_actions",
"crates/hyper_client",
#
# Extensions
@@ -356,7 +357,9 @@ git2 = { version = "0.19", default-features = false }
globset = "0.4"
heed = { version = "0.20.1", features = ["read-txn-no-tls"] }
hex = "0.4.3"
hyper = "0.14"
hyper = "1.4.1"
hyper-util = "0.1.9"
hyper-rustls = "0.27.3"
html5ever = "0.27.0"
ignore = "0.4.22"
image = "0.25.1"

View File

@@ -7,7 +7,6 @@ use anyhow::{anyhow, Context, Result};
use chrono::{DateTime, Utc};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
use isahc::config::Configurable;
use isahc::http::{HeaderMap, HeaderValue};
use serde::{Deserialize, Serialize};
use strum::{EnumIter, EnumString};

View File

@@ -16,7 +16,7 @@ path = "src/http_client.rs"
doctest = true
[dependencies]
http = "0.2"
http = "1.1.0"
anyhow.workspace = true
derive_more.workspace = true
futures.workspace = true

View File

@@ -0,0 +1,45 @@
use anyhow::Error;
use futures::future::BoxFuture;
use http::{Response, Uri};
use hyper_util::client::legacy::{connect::HttpConnector, Client};
struct HyperBasedHttpClient {
client: Client<HttpConnector, Vec<u8>>,
}
struct Executor {
executor: gpui::BackgroundExecutor,
}
impl impl HyperBasedHttpClient {
pub fn new() -> Self {
Self {
client: Client::builder().build(HttpConnector::new()),
}
}
}
impl HttpClient for HyperBasedHttpClient {
fn proxy(&self) -> Option<&Uri> {
None
}
fn send(
&self,
request: HttpRequest,
method: &str,
) -> BoxFuture<'static, Result<Response, Error>> {
let request = request.into_hyper_request(method);
Box::pin(async move {
let response = self.client.request(request).await?;
Ok(response.into())
})
}
fn send_response(&self, response: HttpResponse) -> BoxFuture<'static, Result<(), Error>> {
let response = response.into_hyper_response();
Box::pin(async move {
let _ = self.client.request(response).await?;
Ok(())
})
}
}

View File

@@ -0,0 +1,38 @@
[package]
name = "hyper_client"
version = "0.1.0"
edition = "2021"
publish = false
license = "Apache-2.0"
[lints]
workspace = true
[features]
test-support = []
[lib]
path = "src/hyper_client.rs"
doctest = true
[[example]]
name = "client"
path = "examples/client.rs"
[dependencies]
anyhow.workspace = true
derive_more.workspace = true
futures.workspace = true
log.workspace = true
serde.workspace = true
serde_json.workspace = true
smol.workspace = true
url.workspace = true
gpui.workspace = true
http_client.workspace = true
ureq = "2.10.1"
hyper.workspace = true
hyper-util = {workspace = true, features = ["client", "http1", "http2", "client-legacy"]}
hyper-rustls.workspace = true

View File

@@ -0,0 +1,20 @@
use futures::AsyncReadExt;
use http_client::{AsyncBody, HttpClient};
use hyper_client::UreqHttpClient;
fn main() {
gpui::App::headless().run(|cx| {
dbg!(std::thread::current().id());
cx.spawn(|cx| async move {
let resp = UreqHttpClient::new(cx.background_executor().clone())
.get("http://zed.dev", AsyncBody::empty(), false)
.await
.unwrap();
let mut body = String::new();
resp.into_body().read_to_string(&mut body).await.unwrap();
dbg!(&body.len());
})
.detach();
})
}

View File

@@ -0,0 +1,144 @@
use std::io::Read;
use std::{pin::Pin, task::Poll};
use anyhow::Error;
use futures::channel::mpsc;
use futures::future::BoxFuture;
use futures::{AsyncRead, StreamExt};
use gpui::AppContext;
use http_client::{http, AsyncBody, HttpClient, Inner};
use hyper::body::{Body, Bytes, Frame, Incoming, SizeHint};
use hyper::http::{Response, Uri};
use hyper_util::client::legacy::{connect::HttpConnector, Client};
use smol::future::FutureExt;
use std::future::Future;
pub struct UreqHttpClient {
client: ureq::Agent,
background_executor: gpui::BackgroundExecutor,
}
impl UreqHttpClient {
pub fn new(background_executor: gpui::BackgroundExecutor) -> Self {
Self {
client: ureq::agent(),
background_executor,
}
}
}
struct UreqResponseReader {
task: gpui::Task<()>,
receiver: mpsc::Receiver<std::io::Result<Vec<u8>>>,
buffer: Vec<u8>,
}
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.try_send(Err(e));
break;
}
};
let _ = sender.try_send(Ok(buffer[..n].to_vec()));
}
});
UreqResponseReader {
task,
receiver,
buffer: Vec::new(),
}
}
}
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>> {
let now = std::time::Instant::now();
if self.buffer.is_empty() {
match self.receiver.poll_next_unpin(cx) {
Poll::Ready(Some(Ok(data))) => self.buffer.extend(data),
Poll::Ready(Some(Err(e))) => return Poll::Ready(Err(e)),
Poll::Ready(None) => return Poll::Ready(Ok(0)), // EOF
Poll::Pending => {
dbg!(now.elapsed());
return Poll::Pending;
}
}
}
let n = std::cmp::min(buf.len(), self.buffer.len());
dbg!(buf.len(), self.buffer.len(), now.elapsed());
dbg!(std::thread::current().id());
buf[..n].copy_from_slice(&self.buffer[..n]);
self.buffer.drain(..n);
Poll::Ready(Ok(n))
}
}
impl HttpClient for UreqHttpClient {
fn proxy(&self) -> Option<&Uri> {
None
}
fn send_with_redirect_policy(
&self,
request: http::Request<AsyncBody>,
follow_redirects: bool,
) -> BoxFuture<'static, Result<http::Response<AsyncBody>, Error>> {
let method = request.method().clone();
let url = request.uri().to_string();
let headers = request.headers().clone();
let mut req = self.client.request(method.as_str(), &url);
for (name, value) in headers.iter() {
req = req.set(name.as_str(), value.to_str().unwrap());
}
let executor = self.background_executor.clone();
let req = executor.spawn(async move {
let resp = req.send(request.into_body());
dbg!(std::thread::current().id());
resp
});
// Set follow_redirects policy
// req = req.redirects(if follow_redirects { 10 } else { 0 });
async move {
// Set headers
// Send the request
let response = req.await?;
dbg!(std::thread::current().id());
// Convert ureq response to http::Response
let mut builder = http::Response::builder()
.status(response.status())
.version(http::Version::HTTP_11);
// Set response headers
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()
}
}