#Hyper Reverse Proxy
4 messages · Page 1 of 1 (latest)
impl ProxyHandler {
pub fn new(balancer: Arc<dyn LoadBalancer>) -> Self {
let connector = HttpConnector::new();
Self {
client: Client::builder(TokioExecutor::new()).build(connector),
load_balancer: balancer,
}
}
pub async fn handle(&self, req: Request<Body>) -> Response<Body> {
... // next message
}
async fn forward_request(&self, mut req: Request<Body>, uri: Uri) -> Result<Response<Body>, StatusCode> {
*req.uri_mut() = uri;
Ok(self.client
.request(req)
.await
.map_err(|e| {
log::error!("Error forwarding request: {:?}", e);
StatusCode::BAD_REQUEST
})?
.into_response())
}
}
pub async fn handle(&self, req: Request<Body>) -> Response<Body> {
let timeout_duration = std::time::Duration::from_secs(5);
let selected_lb = self.load_balancer.next().await;
match selected_lb {
Some(lb ) => {
let uri = self.build_backend_uri(&req, &lb.server);
match timeout(timeout_duration, self.forward_request(req, uri)).await {
Ok(Ok(mut response)) => {
log::trace!("Response recieved: {:?}", response);
response.extensions_mut().insert(lb);
response
},
Ok(Err(e)) => {
Response::builder()
.status(e)
.body(Body::from("Bad request"))
.unwrap()
},
Err(_) => {
log::warn!("Request to backend timed out");
Response::builder()
.status(504)
.body(Body::from("Gateway Timeout"))
.unwrap()
}
}
},
None => {
Response::builder()
.status(503)
.body(Body::from("Service Unavailable"))
.unwrap()
}
}
}
Here is my https server:
pub async fn start_https_server(mut app: Router, tcp_listener: TcpListener) -> Result<(), Box<dyn std::error::Error>> {
let rustls_config = rustls_server_config(
PathBuf::from("certs/key.pem"),
PathBuf::from("certs/cert.pem"),
)?;
let tls_acceptor = TlsAcceptor::from(rustls_config);
Pin::new(&mut app);
loop {
let tower_service: Router = app.clone();
let tls_acceptor = tls_acceptor.clone();
let (cnx, addr) = tcp_listener.accept().await.unwrap();
tokio::spawn(async move {
let Ok(stream) = tls_acceptor.accept(cnx).await else {
log::error!("Error during tls handshake connection from {}", addr);
return;
};
let stream = TokioIo::new(stream);
let hyper_service = hyper::service::service_fn(move |request: Request<Incoming>| {
tower_service.clone().oneshot(request)
});
let ret = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new())
.serve_connection_with_upgrades(stream, hyper_service)
.await;
if let Err(err) = ret {
log::warn!("eError serving connection from {}: {}", addr, err);
}
});
}
}