use std::sync::Arc;
use axum::{body::Body, extract::Request, response::Response};
use ic_bn_lib_common::{
traits::http::{Client, ClientHttp},
types::http::Error,
};
use url::Url;
use super::{body::SyncBody, headers::strip_connection_headers};
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 ic_bn_lib_common::traits::http::Client;
use crate::http::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));
}
}