Need help on using Service/NewService in Hyper 0.12.5

I did similar with hyper 0.11, but don’t know how to get it works with hyper 0.12:

extern crate hyper;
extern crate futures;

use hyper::service::{NewService, Service};
use hyper::{Body,Error,Response,StatusCode,Request,Server};
use futures::{future, Future};

struct TestServer {
    something: u64,
}

impl NewService for TestServer {
    type ReqBody = Body;
    type ResBody = Body;
    type Error = Error;
    type InitError = Error;
    type Service = TestServer;
    type Future = Box<Future<Item = Self::Service, Error = Self::InitError> + Send>;
    fn new_service(&self) -> Self::Future {
        Box::new(future::ok(Self {
            something: self.something,
        }))
    }
}

impl Service for TestServer {
    type ReqBody = Body;
    type ResBody = Body;
    type Error = Error;
    type Future = Box<Future<Item = Response<Body>, Error = Error> + Send>;
    fn call(&mut self, _req: Request<Self::ReqBody>) -> Self::Future {
        let something = self.something.to_string();
        Box::new(future::ok(
            Response::builder()
                .status(StatusCode::OK)
                .body(something.into())
                .unwrap()
        ))
    }
}

impl TestServer {
    fn start(self, port: u16) {
        let addr = format!("0.0.0.0:{}", port).parse().unwrap();
        let server = Server::bind(&addr).serve(self);
        println!("Serving at {}", addr);

        hyper::rt::run(server); //<=========================== Error here!
    }
}

fn main() {
    let test = TestServer{something:42};
    test.start(8888);
}

Error:

error[E0271]: type mismatch resolving `<hyper::Server<hyper::server::conn::AddrIncoming, TestServer> as futures::Future>::Error == ()`
  --> src/main.rs:47:9
   |
47 |         hyper::rt::run(server);
   |         ^^^^^^^^^^^^^^ expected struct `hyper::Error`, found ()
   |
   = note: expected type `hyper::Error`
              found type `()`
   = note: required by `hyper::rt::run`

I also try to do similar to this, but it failed too:

        let mut runtime = tokio::runtime::Runtime::new()?;
        runtime.spawn(server);

Does this piece of code have any chance to compile and run with hyper 0.12?

You need to handle the Error part of the future returned in serve(self). For example:

let server = Server::bind(&addr)
            .serve(self)
            .map_err(|e| eprintln!("error: {}", e));

This just prints it to stderr, but you may want to plug something else in (e.g. logging). The gist is the future you give to hyper::rt::run must not return anything (i.e. Item = ()) and not error (i.e. Error = ()). If the future you’re working with returns something else in those types, then you need to map them away to ().

Thank you very much! The sample code works. But it took a half of my day to get my real code to work.

For anyone who hit the same problem as me: Make sure that both Future of NewService and Service trait have Send in them:

type Future = Box<Future<Item = Self::Service, Error = Self::InitError> + Send>; // Need Send
type Future = Box<Future<Item = Response<Body>, Error = Error> + Send>;     // Need Send

The problem is that the compiler complains about futures::Future is not satisfied for hyper::Server, which is incorrect. This make me lost my day!

Yeah, I sympathize. The compiler is correct though - Server implements Future only when all of the where clause bounds are satisfied; in complex bounds, this can be non-obvious, particularly if not familiar with this.

Perhaps the compiler can generate a better error message, indicating which part(s) weren’t satisfied.