use std::sync::Arc;
use axum::{body::Body, extract::Request, response::Response};
use url::Url;
use super::{body::SyncBody, headers::strip_connection_headers};
use crate::http::{
Error,
client::{Client, ClientHttp},
};
pub async fn proxy(
url: Url,
request: Request,
http_client: &Arc<dyn Client>,
) -> Result<Response, Error> {
let (mut parts, body) = request.into_parts();
strip_connection_headers(&mut parts.headers);
let mut request = reqwest::Request::new(parts.method.clone(), url);
*request.headers_mut() = parts.headers;
*request.body_mut() = Some(reqwest::Body::wrap(SyncBody::new(body)));
let response = http_client.execute(request).await?;
let response: http::Response<_> = response.into();
let (parts, body) = response.into_parts();
Ok(Response::from_parts(parts, Body::new(body)))
}
pub async fn proxy_http<B>(
mut request: Request<B>,
http_client: &Arc<dyn ClientHttp<B>>,
) -> Result<Response, Error> {
strip_connection_headers(request.headers_mut());
let response = http_client.execute(request).await?;
let (parts, body) = response.into_parts();
Ok(Response::from_parts(parts, Body::new(body)))
}
#[cfg(test)]
mod test {
use std::sync::Arc;
use axum::{body::Body, extract::Request};
use http_body::Body as _;
use crate::http::{client::Client, proxy::proxy};
#[derive(Debug)]
struct HttpClient;
#[async_trait::async_trait]
impl Client for HttpClient {
async fn execute(&self, _: reqwest::Request) -> Result<reqwest::Response, reqwest::Error> {
Ok(reqwest::Response::from(
http::response::Builder::new()
.status(200)
.body(reqwest::Body::from("foobarbaz"))
.unwrap(),
))
}
}
#[tokio::test]
async fn test_size_hint() {
let cli = Arc::new(HttpClient) as Arc<dyn Client>;
let url = url::Url::parse("http://foo.bar").unwrap();
let request = Request::new(Body::empty());
let resp = proxy(url, request, &cli).await.unwrap();
assert_eq!(resp.body().size_hint().exact(), Some(9));
}
}