refactor(server): expose Http that implements ServerProto

The main changes are:

* The entry point is how `Http`, the implementation of `ServerProto`.
  This type has a `new` constructor as well as builder methods to
  configure it.

* A high-level entry point of `Http::bind` was added which returns a
  `Server`. Binding a protocol to a port requires a socket address
  (where to bind) as well as the instance of `NewService`. Internally
  this creates a core and a TCP listener.

* The returned `Server` has a few methods to learn about itself, e.g.
  `local_addr` and `handle`, but mainly has two methods: `run` and
  `run_until`.

* The `Server::run` entry point will execute a server infinitely, never
  having it exit.

* The `Server::run_until` method is intended as a graceful shutdown
  mechanism. When the provided future resolves the server stops
  accepting connections immediately and then waits for a fixed period of
  time for all active connections to get torn down, after which the
  whole server is torn down anyway.

* Finally a `Http::bind_connection` method exists as a low-level entry
  point to spawning a server connection. This is used by `Server::run`
  as is intended for external use in other event loops if necessary or
  otherwise low-level needs.

BREAKING CHANGE: `Server` is no longer the pimary entry point. Instead,
  an `Http` type is created  and then either `bind` to receiver a `Server`,
  or it can be passed to other Tokio things.
This commit is contained in:
Alex Crichton
2017-01-18 14:09:20 -08:00
committed by Sean McArthur
parent 39a53fcd33
commit f45e9c8e4f
6 changed files with 395 additions and 281 deletions

View File

@@ -3,13 +3,15 @@
extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate pretty_env_logger;
extern crate test;
extern crate tokio_core;
use std::net::SocketAddr;
use futures::{Future, Stream};
use tokio_core::reactor::Core;
use tokio_core::reactor::{Core, Handle};
use tokio_core::net::TcpListener;
use hyper::client;
use hyper::header::{ContentLength, ContentType};
@@ -22,9 +24,7 @@ fn get_one_at_a_time(b: &mut test::Bencher) {
let _ = pretty_env_logger::init();
let mut core = Core::new().unwrap();
let handle = core.handle();
let addr = hyper::Server::http(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap()
.handle(|| Ok(Hello), &handle).unwrap();
let addr = spawn_hello(&handle);
let client = hyper::Client::new(&handle);
@@ -47,9 +47,7 @@ fn post_one_at_a_time(b: &mut test::Bencher) {
let _ = pretty_env_logger::init();
let mut core = Core::new().unwrap();
let handle = core.handle();
let addr = hyper::Server::http(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap()
.handle(|| Ok(Hello), &handle).unwrap();
let addr = spawn_hello(&handle);
let client = hyper::Client::new(&handle);
@@ -92,3 +90,17 @@ impl Service for Hello {
}
}
fn spawn_hello(handle: &Handle) -> SocketAddr {
let addr = "127.0.0.1:0".parse().unwrap();
let listener = TcpListener::bind(&addr, handle).unwrap();
let addr = listener.local_addr().unwrap();
let handle2 = handle.clone();
handle.spawn(listener.incoming().for_each(move |(socket, addr)| {
let http = hyper::server::Http::new();
http.bind_connection(&handle2, socket, addr, Hello);
Ok(())
}).then(|_| Ok(())));
return addr
}