Move request sending to client sub module

This commit is contained in:
Filip Tibell 2025-04-26 22:36:47 +02:00
parent c92d086123
commit 48e34b8c98
3 changed files with 89 additions and 77 deletions

View file

@ -1,2 +1,82 @@
use hyper::{
body::{Bytes, Incoming},
client::conn::http1::handshake,
header::LOCATION,
Method, Request as HyperRequest, Response as HyperResponse, Uri,
};
use mlua::prelude::*;
use crate::{
client::stream::HttpRequestStream,
shared::{
hyper::{HyperExecutor, HyperIo},
request::Request,
response::Response,
},
};
pub mod config;
pub mod stream;
const MAX_REDIRECTS: usize = 10;
/**
Sends the request and returns the final response.
This will follow any redirects returned by the server,
modifying the request method and body as necessary.
*/
pub async fn send_request(mut request: Request, lua: Lua) -> LuaResult<Response> {
loop {
let stream = HttpRequestStream::connect(request.inner.uri()).await?;
let (mut sender, conn) = handshake(HyperIo::from(stream)).await.into_lua_err()?;
HyperExecutor::execute(lua.clone(), conn);
let incoming = sender
.send_request(request.as_full())
.await
.into_lua_err()?;
if let Some((new_method, new_uri)) = check_redirect(&request.inner, &incoming) {
if request.redirects >= MAX_REDIRECTS {
return Err(LuaError::external("Too many redirects"));
}
if new_method == Method::GET {
*request.inner.body_mut() = Bytes::new();
}
*request.inner.method_mut() = new_method;
*request.inner.uri_mut() = new_uri;
request.redirects += 1;
continue;
}
break Response::from_incoming(incoming, request.decompress).await;
}
}
fn check_redirect(
request: &HyperRequest<Bytes>,
response: &HyperResponse<Incoming>,
) -> Option<(Method, Uri)> {
if !response.status().is_redirection() {
return None;
}
let location = response.headers().get(LOCATION)?;
let location = location.to_str().ok()?;
let location = location.parse().ok()?;
let method = match response.status().as_u16() {
301..=303 => Method::GET,
_ => request.method().clone(),
};
Some((method, location))
}

View file

@ -39,7 +39,6 @@ pub fn module(lua: Lua) -> LuaResult<LuaTable> {
}
async fn net_request(lua: Lua, config: RequestConfig) -> LuaResult<Response> {
Request::from_config(config, lua.clone())?
.send(lua.clone())
.await
let request = Request::from_config(config, lua.clone())?;
self::client::send_request(request, lua.clone()).await
}

View file

@ -2,32 +2,22 @@ use http_body_util::Full;
use url::Url;
use hyper::{
body::{Bytes, Incoming},
client::conn::http1::handshake,
header::{HeaderName, HeaderValue, LOCATION, USER_AGENT},
HeaderMap, Method, Request as HyperRequest, Response as HyperResponse, Uri,
body::Bytes,
header::{HeaderName, HeaderValue, USER_AGENT},
HeaderMap, Request as HyperRequest,
};
use mlua::prelude::*;
use crate::{
client::{config::RequestConfig, stream::HttpRequestStream},
shared::{
headers::create_user_agent_header,
hyper::{HyperExecutor, HyperIo},
response::Response,
},
};
const MAX_REDIRECTS: usize = 10;
use crate::{client::config::RequestConfig, shared::headers::create_user_agent_header};
#[derive(Debug, Clone)]
pub struct Request {
// NOTE: We use Bytes instead of Full<Bytes> to avoid
// needing async when getting a reference to the body
inner: HyperRequest<Bytes>,
redirects: usize,
decompress: bool,
pub(crate) inner: HyperRequest<Bytes>,
pub(crate) redirects: usize,
pub(crate) decompress: bool,
}
impl Request {
@ -100,43 +90,6 @@ impl Request {
let body = Full::new(self.inner.body().clone());
builder.body(body).expect("request was valid")
}
/**
Sends the request and returns the final response.
This will follow any redirects returned by the server,
modifying the request method and body as necessary.
*/
pub async fn send(mut self, lua: Lua) -> LuaResult<Response> {
loop {
let stream = HttpRequestStream::connect(self.inner.uri()).await?;
let (mut sender, conn) = handshake(HyperIo::from(stream)).await.into_lua_err()?;
HyperExecutor::execute(lua.clone(), conn);
let incoming = sender.send_request(self.as_full()).await.into_lua_err()?;
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 new_method == Method::GET {
*self.inner.body_mut() = Bytes::new();
}
*self.inner.method_mut() = new_method;
*self.inner.uri_mut() = new_uri;
self.redirects += 1;
continue;
}
break Response::from_incoming(incoming, self.decompress).await;
}
}
}
fn add_default_headers(lua: &Lua, headers: &mut HeaderMap) -> LuaResult<()> {
@ -148,23 +101,3 @@ fn add_default_headers(lua: &Lua, headers: &mut HeaderMap) -> LuaResult<()> {
Ok(())
}
fn check_redirect(
request: &HyperRequest<Bytes>,
response: &HyperResponse<Incoming>,
) -> Option<(Method, Uri)> {
if !response.status().is_redirection() {
return None;
}
let location = response.headers().get(LOCATION)?;
let location = location.to_str().ok()?;
let location = location.parse().ok()?;
let method = match response.status().as_u16() {
301..=303 => Method::GET,
_ => request.method().clone(),
};
Some((method, location))
}