use std::{str::FromStr, sync::Arc}; use bytes::Bytes; use reqwest::{ Method, header::{HeaderMap, HeaderName, HeaderValue}, redirect::Policy, }; use crate::settings::Result; use super::{Connection, HttpRequest, HttpResponse, ServerProxyService}; pub struct ReqwestProxy { client: reqwest::Client, } #[async_trait::async_trait] impl ServerProxyService for ReqwestProxy { async fn new() -> Arc { Self { client: reqwest::ClientBuilder::new() .redirect(Policy::none()) .build() .expect("Can't build client"), } .into() } async fn fetch(&self, req: HttpRequest, connection: Connection) -> Result { let mut headers = HeaderMap::new(); for (key, value) in req.headers { headers.append(key.parse::()?, value.parse::()?); } let res = self .client .request( Method::from_str(&req.method)?, format!( "{}://{}:{}{}", connection.protocol, connection.ip_address, connection.port, req.path ), ) .headers(headers) .body(req.body) .send() .await?; let headers = res .headers() .iter() .map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string())) .collect(); Ok(HttpResponse::new( res.status().as_u16(), headers, res.bytes().await.ok().unwrap_or_else(|| Bytes::new()), )) } }