I'm making a proxy server using tokio
and hyper
. Depending on the request, there can be multiple proxy servers(can send request). I have the addresses of the servers to proxy as a vector and try to connect in turn.
For example, when a GET /test HTTP/1.1
request is received, there are proxy server candidates named ["aaa.com", "bbb.com", "ccc.com"]. My server tries to connect in the order aaa -> bbb -> ccc and sends a proxy request to the server where the connection succeeds. If it cannot connect to all servers, a 500 error is returned.
The problem is that the same request must be sent until the connection to the server is successful, but if use hyper
's method, the request is consumed and a problem occurs in the next loop. But I couldn't find a way to copy hyper::Request
(clone
, etc.) How can I copy a hyper::Request
in Rust?
fn proxy(
mut req: Request<hyper::Body>,
) -> BoxFuture<'static, Response<hyper::Body>> {
let route = req
.extensions_mut()
.remove::<RoutingInfo>()
.expect("route not found.");
let size = route.api_config.target_servers.len();
Box::pin(async move {
let mut index = 1;
let resp = loop {
let target_server = schedule_server(&route);// get "aaa.com" or "bbb.com" or "ccc.com"
let https = HttpsConnectorBuilder::new()
.with_native_roots()
.https_or_http()
.enable_http1()
.build();
let client = Client::builder().build::<_, RawBody>(https);
let destination = format!("{}{}", target_server, route.target_uri);
*req.uri_mut() = destination.parse::<Uri>().unwrap();
match client.request(req).await {
Ok(resp) => {
break resp;
},
Err(_e) => {//TODO: only connection error
if index == size {
break Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(hyper::Body::empty())
.unwrap();
}
index++;
}
};
};
resp
})
}
error[E0382]: borrow of moved value: `req`
--> src/service/proxy.rs:83:14
|
83 | *req.uri_mut() = destination.parse::<Uri>().unwrap();
| ^^^^^^^^^^^^^ value borrowed here after move
...
87 | match client.request(req).await {
| --- value moved here, in previous iteration of loop