0

I am trying to write a simple REST server using hyper:


pub struct APIServer{
    port: u16,
    memtable: RwLock<Memtable>
}

#[derive(Deserialize, Debug)]
pub struct KeyValuePair {
    key : String,
    value : String,
}

impl APIServer {
    pub fn new(port: u16, path: String) -> Result<APIServer, io::Error> {
        let path = Path::new(&path);
        let memtable = Memtable::new(path)?;

        let server = APIServer {
            port: port,
            memtable: RwLock::<Memtable>::from(memtable),
        };
        Ok(server)
    }

    pub async fn run(&self) {
        let addr = SocketAddr::from(([127, 0, 0, 1], self.port));

        println!("Listening on {}", addr);     

        let serve_future = Server::bind(&addr).serve(make_service_fn(|_conn| {
            async {
                {
                    Ok::<_, hyper::Error>(service_fn(router))
                }
            }
        }));

        // Wait for the server to complete serving or exit with an error.
        // If an error occurred, print it to stderr.
        if let Err(e) = serve_future.await {
            eprintln!("server error: {}", e);
        }
    }


    // Router routes requests to approporiate http handlers.
    fn router(&self) -> Box<dyn Fn(Request<Body>) -> Result<Response<Body>, hyper::Error>> {
        return Box::new(|req| async move {
            let mut response = Response::new(Body::empty());

            match (req.method(), req.uri().path()) {
                (&Method::GET, "/{key}") => {
                    handlers::get_value(req)
                }
                (&Method::POST, "/") => {
                    handlers::write_key_value_pair(req).await
                }
                _ => {
                    *response.status_mut() = StatusCode::NOT_FOUND;
                    Ok(response)
                }
            }
        });
    }
}

The issue is that I would like to use the APIServers fields inside the the http handlers (and the router itself) - i.e. use them as a "service_fn"(1,2), thus, their signature would be fn foo_handler(Request<Body>) -> Result<Response<Body>, hyper::Error:error> - to resolve this issue I made the router return a closure which contains adheres to the above signature.

But now I am getting the following error:


expected enum `std::result::Result`, found opaque type

note:     expected enum `std::result::Result<http::response::Response<hyper::body::body::Body>, hyper::error::Error>`
      found opaque type `impl futures::Future`rustc(E0308)
server.rs(58, 31): expected enum `std::result::Result`, found opaque type

In short, how can I use the router and the handlers as methods so that I can pass certain private fields to them? without breaching contract.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Nimrodshn
  • 859
  • 3
  • 13
  • 29
  • Your code is missing a few important pieces, like the handlers module – could you provide a minimal example that allows reproducing the error? – nnnmmm Mar 29 '20 at 09:20
  • That said, could it be that the issue is that your function signature says you'll return a regular Result, yet you return an `async` closure, i.e. something that returns a future of a Result? – nnnmmm Mar 29 '20 at 09:21

0 Answers0