How to store a hyper::server::Server as a field in a struct

hey guys

I am trying to store a hyper::server::Server as a field in a struct

check out the code here how can i correct the error:

You had two trivial errors: one syntax error (a missing semicolon) and an apparent misunderstanding about how methods are bound (App::new(); creates an instance and throws it away immediately, and App::run_until_stopped() doesn't compile because there is no instance to bind to the self argument.)

After fixing these, the resulting type error isn't related to "storing the server as a field". It's perfectly fine to store any kind of value in any field.

The error is related to the generic type parameter, but it's not possible to solve using generics. A generic type parameter is chosen by the user of the type. It can be anything, a generic type/fn doesn't know what concrete type the type parameter will be substituted with (that's the whole point of generics). But here, you are trying to substitute a very specific type (MakeServiceFn<_>) for the type parameter S. That's not going to work, because what should happen when the caller chooses something else? (Alas, they couldn't even choose this specific type ever, even if they wanted to, because it contains a closure type, which is unique and unnameable.)

Now, since the concrete type is unnameable, you could instead create a trait object from the trait you want to use later, so Box<dyn TheTraitReturnedByMakeServiceFn>. Alas, that trait is hyper::service::make::MakeServiceRef, which is private, so you can't use it either.

It looks like the easier solution would be to just store the address instead of the server, and perform the binding and the creation of the internal service handler functions in App::run_until_stopped():

pub struct App {
    addr: SocketAddr,
}

impl App {
    pub async fn new() -> Self {
        let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
        App { addr }
    }
    
    pub async fn run_until_stopped(self) -> Result<(), hyper::Error> {
        let make_svc = make_service_fn(|_conn| async {
            // service_fn converts our function into a `Service`
            Ok::<_, Infallible>(service_fn(hello_world))
        });
        let server = Server::bind(&self.addr).serve(make_svc);
        
        server.await
    }
}

Playground

1 Like