use http_body_util::Full;
use hyper::{
Method, Request as HyperRequest,
client::conn::http1::handshake,
header::{ACCEPT, CONTENT_LENGTH, HOST, HeaderValue, USER_AGENT},
};
use mlua::prelude::*;
use url::Url;
use crate::{
client::stream::HttpStream,
shared::{
headers::create_user_agent_header,
hyper::{HyperExecutor, HyperIo},
request::Request,
response::Response,
},
};
pub async fn send(mut request: Request, lua: Lua) -> LuaResult<Response> {
let mut url = request
.inner
.uri()
.to_string()
.parse::<Url>()
.into_lua_err()?;
if !request.headers().contains_key(USER_AGENT.as_str()) {
let ua = create_user_agent_header(&lua)?;
let ua = HeaderValue::from_str(&ua).unwrap();
request.inner.headers_mut().insert(USER_AGENT, ua);
}
if !request.headers().contains_key(CONTENT_LENGTH.as_str()) && request.method() != Method::GET {
let len = request.body().len().to_string();
let len = HeaderValue::from_str(&len).unwrap();
request.inner.headers_mut().insert(CONTENT_LENGTH, len);
}
if !request.headers().contains_key(ACCEPT.as_str()) {
let accept = HeaderValue::from_static("*/*");
request.inner.headers_mut().insert(ACCEPT, accept);
}
loop {
let stream = HttpStream::connect_url(url.clone()).await?;
let (mut sender, conn) = handshake(HyperIo::from(stream)).await.into_lua_err()?;
HyperExecutor::execute(lua.clone(), conn);
let (mut parts, body) = request.clone_inner().into_parts();
if let Some(host) = parts.uri.host() {
let host = HeaderValue::from_str(host).unwrap();
parts.headers.insert(HOST, host);
}
let data = HyperRequest::from_parts(parts, Full::new(body.into_bytes()));
let incoming = sender.send_request(data).await.into_lua_err()?;
if super::try_follow_redirect(&mut url, &mut request, &incoming)
.map_err(LuaError::external)?
{
continue;
}
break Response::from_incoming(incoming, request.decompress).await;
}
}