Ahoj, mam takovej vypecenej problem. Pisu https_proxy s podporou kerbera nad hyperem, v zakladu mi to nejak fungovalo i rozhod sem se prepsat to state machine a tady sem narazil. Mam problem ze kdyz vyhodnotim connect, musim upgradovat spojeni, ale to mi neprezije context. Kod vypada nejak takhle:
pub struct RequestContext {
.
pub proxy_stream: Option<tokio::net::TcpStream>,
}
impl RequestState {
pub async fn next(self, ctx: &mut RequestContext) -> RequestState {
match self {
.
RequestState::ConnectingToProxy => ctx.handle_connecting_to_proxy().await,
RequestState::Tunelling => ctx.handle_tunelling().await,
.
}
}
}
pub async fn handle_tunelling(&mut self) -> RequestState {
let mut proxy_stream = self.proxy_stream.as_mut().unwrap(); // nemuzu udelat take protoze pak uz nemam ten stream nejspis:
let proxy_string = self.ap_req.as_ref().unwrap();
let host = self.original_request.as_ref().unwrap().uri().host().unwrap_or("localhost");
let connect_req = format!(
"CONNECT {} HTTP/1.1\r\nHost: {}\r\nProxy-Authorization: {}\r\n\r\n",
self.original_request.as_ref().unwrap().uri(), host, proxy_string
);
tokio::task::spawn(async move {
let upgraded_client = on_upgrade.await.unwrap();
let mut client_io = TokioIo::new(upgraded_client);
tokio::io::copy_bidirectional(&mut client_io, &mut proxy_stream).await.unwrap();
});
self.original_response = Some(resp_to_client.map(|b| b.boxed()));
return RequestState::Closing;
}
a jeste main a state machine:
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.
tokio::task::spawn(async move {
if let Err(err) = ServerBuilder::new()
.preserve_header_case(true)
.title_case_headers(true)
.serve_connection(io, service_fn(request_machine))
.with_upgrades()
.await
{
println!("Failed to serve connection: {:?}", err);
}
});
}
}
async fn request_machine(req: Request<hyper::body::Incoming>) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
let mut state = RequestState::WaitingForRequest;
let mut context = RequestContext::new(req).await;
loop {
state = state.next(&mut context).await;
if matches!(state, RequestState::Closing) {
break; // konec práce
}
}
println!("state: {:?}", context);
let response = context.original_response.take().unwrap();
Ok(response.map(|b| b.boxed()))
}
Proste sem se zasek na tom ze netusim jak to udelat aby v ramci Tokia prezil tcpstream z vyssich fci te state machine. Nejde udelat clone() toho streamu. AI doporucuju try_clone ale ten vubec neexistuje. Neresil nekdy nekdo neco takovyho ? Kod je zkracenej, muzu doplnit. Jinak pokud to udelam naprasaka v ramci toho hyper handleru tak to vsechno jak vino (ale to nechci).