I am struggling to build a web service using Hyper. The problem I face is best illustrated with with example code ...
use std::convert::Infallible;
use std::sync::Arc;
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
struct ContrivedServicesManager {
some_state: Vec<String>
}
impl ContrivedServicesManager {
pub /* async */ fn handle_request(&self, _req: Request<Body>) -> Response<Body> {
hyper::Response::new(Body::from(self.some_state.join(", ")))
}
fn new(args: Vec<String>) -> Self {
Self {
some_state: args
}
}
}
#[tokio::main]
async fn main() {
// Grab all the command line arges following argv[0]
let args: Vec<String> = std::env::args()
.enumerate()
.filter(|&(i,_)| i > 0)
.map(|(_, e)| e)
.collect();
// The inner layer of request handling machinery
let services_manager = Arc::new(ContrivedServicesManager::new(args));
// Build the outer layer of request handling machinery
let service_maker = make_service_fn(move |_| {
let services_manager = services_manager.clone();
return async move {
Ok::<_, Infallible>(service_fn(move |req| {
let response = services_manager.handle_request(req);
async move { Ok::<_, Infallible>(
response
)}
}))
};
});
// Configure & start the web server
let addr = ([127, 0, 0, 1], 3000).into();
let server = Server::bind(&addr).serve(service_maker);
println!("Listening on http://{}", addr);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
This compiles & works. However, if ContrivedServicesManager::handle_request
is changed to be async
it fails to compile and the compiler outputs 237 lines of complaint, which seem to centre on service_maker
being the wrong type.
I would be so glad if someone with stronger Rust-Fu would tell me how to overcome this.