0

I'm trying to make a small HTTP router using hyper, but I'm having some difficulties starting the server.

The following function is where I'm having trouble.

Dependencies:

[dependencies]
hyper = "0.13"
tokio = { version = "0.2", features = ["full"] }
use std::net::SocketAddr;
use std::convert::Infallible;
use hyper::Server;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response};

#[tokio::main]
async fn main() {
    let router = Router::new(SocketAddr::from(([127, 0, 0, 1], 80)));
    router.start();
}

pub struct Router<'a> {
    addr: SocketAddr,
}

impl<'a> Router<'a> {
    pub fn new(addr: SocketAddr) -> Self {
        Self {
            addr,
        }
    }

    pub async fn start(&self) {
        let make_svc = make_service_fn(|_| async {
            Ok::<_, Infallible>(service_fn(|req| self.route(req)))
        });

        let server = Server::bind(&self.addr).serve(make_svc);

        println!("Listening on http://{}", self.addr);

        if let Err(e) = server.await {
            eprintln!("Server error: {}", e);
        }
    }

    pub async fn route(&self, req: Request<Body>) -> Result<Response<Body>, Infallible> {
        // TODO

        Ok(Response::new(
            "Hello, world!".into()
        ))
    }
}

I can't use Ok::<_, Infallible>(service_fn(self.route), because one of the arguments is &self. The problem with the solution I found is that the compiler can't infer an appropriate lifetime, and I have no idea how to fix it.

error: cannot infer an appropriate lifetime
  --> src\main.rs:24:24
   |
24 |     pub async fn start(&self) {
   |                        ^^^^^ ...but this borrow...
...
29 |         let server = Server::bind(&self.addr).serve(make_svc);
   |                                               ----- this return type evaluates to the `'static` lifetime...
   |
note: ...can't outlive the lifetime `'_` as defined on the method body at 24:24
  --> src\main.rs:24:24
   |
24 |     pub async fn start(&self) {
   |                        ^

error: aborting due to previous error
Jtplouffe
  • 11
  • 2
  • It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster May 12 '20 at 01:39

1 Answers1

0

Your make_svc uses &self, but that variable is borrowed temporarily only until the end of the start function. The server may exist outside the start function, so it can't refer to borrowed variables in it.

When you use closures for long-lived things like servers, you can't use temporary references. Use Arc instead, e.g. start(self: Arc<Self>) and actually wrap that object in Arc::new() before calling the method.

Kornel
  • 97,764
  • 37
  • 219
  • 309