Skip to content

Commit a2d9275

Browse files
committed
perf(client): stream proxy response body instead of buffering
1 parent 77e23d1 commit a2d9275

1 file changed

Lines changed: 14 additions & 10 deletions

File tree

src/client.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use arc_swap::ArcSwap;
22
use cached::proc_macro::cached;
3+
use bytes::Bytes;
34
use futures_lite::future::block_on;
4-
use futures_lite::{future::Boxed, FutureExt};
5-
use http_body_util::BodyExt;
5+
use futures_lite::{future::Boxed, FutureExt, StreamExt};
6+
use http_body_util::{BodyExt, StreamBody};
7+
use hyper::body::Frame;
68
use hyper::{header, Method, Request, Response};
79
use log::{error, info, trace, warn};
810
use percent_encoding::{percent_encode, CONTROLS};
@@ -13,12 +15,13 @@ use wreq_util::{Emulation, EmulationOS, EmulationOption};
1315

1416
use std::sync::atomic::Ordering;
1517
use std::sync::atomic::{AtomicBool, AtomicU16};
18+
use std::convert::Infallible;
1619
use std::sync::LazyLock;
1720
use std::result::Result;
1821

1922
use crate::dbg_msg;
2023
use crate::oauth::{force_refresh_token, token_daemon, Oauth, OauthBackendImpl};
21-
use crate::server::RequestExt;
24+
use crate::server::{Body, RequestExt};
2225
use crate::utils::{format_url, Post};
2326

2427
const REDDIT_URL_BASE: &str = "https://oauth.reddit.com";
@@ -69,8 +72,6 @@ pub fn build_client() -> WreqClient {
6972
.expect("Should always be able to build a client")
7073
}
7174

72-
use crate::server::{full, Body};
73-
7475
/// Convert a wreq Response into a hyper Response<Body>.
7576
/// wreq and hyper now both use http v1.x, so header types are directly compatible.
7677
trait IntoHyperResponse {
@@ -93,15 +94,18 @@ impl IntoHyperResponse for wreq::Response {
9394
}
9495
}
9596

96-
let bytes = self.bytes().await.map_err(|e| e.to_string())?;
97-
// wreq already decompresses; remove the content-encoding header so
98-
// downstream code doesn't try to decompress again.
97+
// wreq already decompresses; drop content-length since the final
98+
// size is unknown without buffering, relying on chunked encoding.
9999
if let Some(h) = builder.headers_mut() {
100100
h.remove(header::CONTENT_ENCODING);
101-
h.insert(header::CONTENT_LENGTH, bytes.len().into());
101+
h.remove(header::CONTENT_LENGTH);
102102
}
103103

104-
builder.body(full(bytes)).map_err(|e| e.to_string())
104+
let stream = self
105+
.bytes_stream()
106+
.filter_map(|r| r.ok().map(|b| Ok::<Frame<Bytes>, Infallible>(Frame::data(b))));
107+
108+
builder.body(BodyExt::boxed(StreamBody::new(stream))).map_err(|e| e.to_string())
105109
}
106110
}
107111

0 commit comments

Comments
 (0)