50 lines
1.5 KiB
Rust
50 lines
1.5 KiB
Rust
use std::pin::Pin;
|
|
|
|
use hyper::{Request, body::Incoming, service::Service};
|
|
use hyper_util::rt::TokioIo;
|
|
use log::error;
|
|
use tokio::net::TcpStream;
|
|
|
|
use crate::server::{GeneralResponse, to_general_response};
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ProxyService {
|
|
pub address: String,
|
|
pub hostname: String,
|
|
}
|
|
|
|
impl Service<Request<Incoming>> for ProxyService {
|
|
type Response = GeneralResponse;
|
|
type Error = hyper::Error;
|
|
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
|
|
|
fn call(&self, incoming: Request<Incoming>) -> Self::Future {
|
|
let address = self.address.clone();
|
|
let hostname = self.hostname.clone();
|
|
Box::pin(async move {
|
|
let stream = TcpStream::connect(address).await.unwrap();
|
|
let io = TokioIo::new(stream);
|
|
|
|
let (mut sender, conn) = hyper::client::conn::http1::Builder::new()
|
|
.handshake(io)
|
|
.await
|
|
.unwrap();
|
|
|
|
tokio::spawn(async move {
|
|
if let Err(err) = conn.await {
|
|
error!("Could not open connection to backend: {err}");
|
|
}
|
|
});
|
|
|
|
let (mut parts, body_stream) = incoming.into_parts();
|
|
|
|
parts
|
|
.headers
|
|
.insert(hyper::header::HOST, hostname.parse().unwrap());
|
|
|
|
let req = Request::from_parts(parts, body_stream);
|
|
|
|
Ok(to_general_response(sender.send_request(req).await.unwrap()))
|
|
})
|
|
}
|
|
}
|