feat(service): introduce hyper-specific Service

This introduces the `hyper::service` module, which replaces
`tokio-service`.

Since the trait is specific to hyper, its associated
types have been adjusted. It didn't make sense to need to define
`Service<Request=http::Request>`, since we already know the context is
HTTP. Instead, the request and response bodies are associated types now,
and slightly stricter bounds have been placed on `Error`.

The helpers `service_fn` and `service_fn_ok` should be sufficient for
now to ease creating `Service`s.

The `NewService` trait now allows service creation to also be
asynchronous.

These traits are similar to `tower` in nature, and possibly will be
replaced completely by it in the future. For now, hyper defining its own
allows the traits to have better context, and prevents breaking changes
in `tower` from affecting hyper.

Closes #1461

BREAKING CHANGE: The `Service` trait has changed: it has some changed
  associated types, and `call` is now bound to `&mut self`.

  The `NewService` trait has changed: it has some changed associated
  types, and `new_service` now returns a `Future`.

  `Client` no longer implements `Service` for now.

  `hyper::server::conn::Serve` now returns `Connecting` instead of
  `Connection`s, since `new_service` can now return a `Future`. The
  `Connecting` is a future wrapping the new service future, returning
  a `Connection` afterwards. In many cases, `Future::flatten` can be
  used.
This commit is contained in:
Sean McArthur
2018-04-17 13:03:59 -07:00
parent 71a15c25f5
commit 2dc6202fe7
24 changed files with 749 additions and 582 deletions

35
src/service/mod.rs Normal file
View File

@@ -0,0 +1,35 @@
//! Services and NewServices
//!
//! - A [`Service`](Service) is a trait representing an asynchronous function
//! of a request to a response. It's similar to
//! `async fn(Request) -> Result<Response, Error>`.
//! - A [`NewService`](NewService) is a trait creating specific instances of a
//! `Service`.
//!
//! These types are conceptually similar to those in
//! [tower](https://crates.io/crates/tower), while being specific to hyper.
//!
//! # Service
//!
//! In hyper, especially in the server setting, a `Service` is usually bound
//! to a single connection. It defines how to respond to **all** requests that
//! connection will receive.
//!
//! While it's possible to implement `Service` for a type manually, the helpers
//! [`service_fn`](service_fn) and [`service_fn_ok`](service_fn_ok) should be
//! sufficient for most cases.
//!
//! # NewService
//!
//! Since a `Service` is bound to a single connection, a [`Server`](::Server)
//! needs a way to make them as it accepts connections. This is what a
//! `NewService` does.
//!
//! Resources that need to be shared by all `Service`s can be put into a
//! `NewService`, and then passed to individual `Service`s when `new_service`
//! is called.
mod new_service;
mod service;
pub use self::new_service::{NewService};
pub use self::service::{service_fn, service_fn_ok, Service};