diff --git a/crates/lune-std-net/src/shared/request.rs b/crates/lune-std-net/src/shared/request.rs index c4c902b..213449a 100644 --- a/crates/lune-std-net/src/shared/request.rs +++ b/crates/lune-std-net/src/shared/request.rs @@ -23,7 +23,9 @@ const MAX_REDIRECTS: usize = 10; #[derive(Debug, Clone)] pub struct Request { - inner: HyperRequest>, + // NOTE: We use Bytes instead of Full to avoid + // needing async when getting a reference to the body + inner: HyperRequest, redirects: usize, decompress: bool, } @@ -65,11 +67,7 @@ impl Request { // 5. Convert request body bytes to the proper Body // type that Hyper expects, if we got any bytes - let body = config - .body - .map(Bytes::from) - .map(Full::new) - .unwrap_or_default(); + let body = config.body.map(Bytes::from).unwrap_or_default(); // 6. Finally, attach the body, verifying that the request // is valid, and attach a user agent if not already set @@ -84,6 +82,25 @@ impl Request { }) } + /** + Returns the inner `hyper` request with its body + type modified to `Full` for sending. + */ + pub fn as_full(&self) -> HyperRequest> { + let mut builder = HyperRequest::builder() + .version(self.inner.version()) + .method(self.inner.method()) + .uri(self.inner.uri()); + + let headers = builder.headers_mut().expect("request was valid"); + for (name, value) in self.inner.headers() { + headers.insert(name, value.clone()); + } + + let body = Full::new(self.inner.body().clone()); + builder.body(body).expect("request was valid") + } + /** Sends the request and returns the final response. @@ -94,30 +111,23 @@ impl Request { loop { let stream = HttpRequestStream::connect(self.inner.uri()).await?; - let (mut sender, conn) = handshake(HyperIo::from(stream)) - .await - .map_err(LuaError::external)?; + let (mut sender, conn) = handshake(HyperIo::from(stream)).await.into_lua_err()?; HyperExecutor::execute(lua.clone(), conn); - let incoming = sender - .send_request(self.inner.clone()) - .await - .map_err(LuaError::external)?; + let incoming = sender.send_request(self.as_full()).await.into_lua_err()?; - if let Some((replacement_method, replacement_uri)) = - check_redirect(&self.inner, &incoming) - { + if let Some((new_method, new_uri)) = check_redirect(&self.inner, &incoming) { if self.redirects >= MAX_REDIRECTS { return Err(LuaError::external("Too many redirects")); } - if replacement_method == Method::GET { - *self.inner.body_mut() = Full::default(); + if new_method == Method::GET { + *self.inner.body_mut() = Bytes::new(); } - *self.inner.method_mut() = replacement_method; - *self.inner.uri_mut() = replacement_uri; + *self.inner.method_mut() = new_method; + *self.inner.uri_mut() = new_uri; self.redirects += 1; @@ -140,7 +150,7 @@ fn add_default_headers(lua: &Lua, headers: &mut HeaderMap) -> LuaResult<()> { } fn check_redirect( - request: &HyperRequest>, + request: &HyperRequest, response: &HyperResponse, ) -> Option<(Method, Uri)> { if !response.status().is_redirection() { diff --git a/crates/lune-std-net/src/shared/response.rs b/crates/lune-std-net/src/shared/response.rs index 3f9b8e8..5efc8c8 100644 --- a/crates/lune-std-net/src/shared/response.rs +++ b/crates/lune-std-net/src/shared/response.rs @@ -1,5 +1,5 @@ use futures_lite::prelude::*; -use http_body_util::BodyStream; +use http_body_util::{BodyStream, Full}; use hyper::{ body::{Body, Bytes, Incoming}, @@ -12,6 +12,8 @@ use crate::shared::headers::header_map_to_table; #[derive(Debug, Clone)] pub struct Response { + // NOTE: We use Bytes instead of Full to avoid + // needing async when getting a reference to the body inner: HyperResponse, decompressed: bool, } @@ -81,6 +83,22 @@ impl Response { pub fn body(&self) -> &[u8] { self.inner.body() } + + /** + Returns the inner `hyper` response with its body + type modified to `Full` for sending. + */ + pub fn as_full(&self) -> HyperResponse> { + let mut builder = HyperResponse::builder().version(self.inner.version()); + + let headers = builder.headers_mut().expect("request was valid"); + for (name, value) in self.inner.headers() { + headers.insert(name, value.clone()); + } + + let body = Full::new(self.inner.body().clone()); + builder.body(body).expect("request was valid") + } } impl LuaUserData for Response {