I want to write an HttpServer
that uses the async-fn-in-trait syntax, and this is the simplified code
#![feature(async_fn_in_trait)]
use std::{convert::Infallible, future::Future, net::SocketAddr, str::FromStr};
use bytes::Bytes;
use http_body_util::Full;
use hyper::{body::Incoming, server::conn::http1, service::service_fn, Request, Response};
use tokio::net::TcpListener;
pub trait Handle {
async fn handle(&mut self, req: Request<Incoming>)
-> Result<Response<Full<Bytes>>, Infallible>;
}
struct HttpServer<H> {
addr: String,
handler: H,
}
impl<H> HttpServer<H>
where
H: Handle,
{
fn servr(&self) {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async move {
let addr = SocketAddr::from_str(self.addr.as_str()).unwrap();
let listener = TcpListener::bind(addr).await.unwrap();
loop {
let (stream, _) = listener.accept().await.unwrap();
tokio::task::spawn(async move {
let service = service_fn(move |req| self.handler.handle(req));
http1::Builder::new()
.serve_connection(stream, service)
.await
.unwrap()
});
}
})
}
}
like Do we need Send bounds to stabilize async_fn_in_trait? says, there will be an "future is not Send
" error
This issue says it can be temporarily solved with the return_position_impl_trait_in_trait syntax
#![feature(return_position_impl_trait_in_trait)]
pub trait Handle: Send + 'static {
fn handle(
&mut self,
req: Request<Incoming>,
) -> impl Future<Output = Result<Response<Full<Bytes>>, Infallible>> + Send + '_;
}
but it still doesn't work.
What is the correct way to get this code to pass compilation?