feat(lib): implement compatibility with http crate
This commit is contained in:
7
src/server/compat.rs
Normal file
7
src/server/compat.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
//! Wrappers to build compatibility with the `http` crate.
|
||||
|
||||
pub use super::compat_impl::{
|
||||
CompatFuture,
|
||||
CompatService,
|
||||
NewCompatService
|
||||
};
|
||||
82
src/server/compat_impl.rs
Normal file
82
src/server/compat_impl.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use std::io::{Error as IoError};
|
||||
|
||||
use futures::{Future, Poll};
|
||||
use http_types;
|
||||
use tokio_service::{NewService, Service};
|
||||
|
||||
use error::Error;
|
||||
use http::Body;
|
||||
use http::request::Request;
|
||||
use http::response::Response;
|
||||
|
||||
/// Wraps a `Future` returning an `http::Response` into
|
||||
/// a `Future` returning a `hyper::server::Response`.
|
||||
#[derive(Debug)]
|
||||
pub struct CompatFuture<F> {
|
||||
future: F
|
||||
}
|
||||
|
||||
impl<F, Bd> Future for CompatFuture<F>
|
||||
where F: Future<Item=http_types::Response<Bd>, Error=Error>
|
||||
{
|
||||
type Item = Response<Bd>;
|
||||
type Error = Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.future.poll()
|
||||
.map(|a| a.map(|res| res.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps a `Service` taking an `http::Request` and returning
|
||||
/// an `http::Response` into a `Service` taking a `hyper::server::Request`,
|
||||
/// and returning a `hyper::server::Response`.
|
||||
#[derive(Debug)]
|
||||
pub struct CompatService<S> {
|
||||
service: S
|
||||
}
|
||||
|
||||
pub fn service<S>(service: S) -> CompatService<S> {
|
||||
CompatService { service: service }
|
||||
}
|
||||
|
||||
impl<S, Bd> Service for CompatService<S>
|
||||
where S: Service<Request=http_types::Request<Body>, Response=http_types::Response<Bd>, Error=Error>
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response<Bd>;
|
||||
type Error = Error;
|
||||
type Future = CompatFuture<S::Future>;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
CompatFuture {
|
||||
future: self.service.call(req.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps a `NewService` taking an `http::Request` and returning
|
||||
/// an `http::Response` into a `NewService` taking a `hyper::server::Request`,
|
||||
/// and returning a `hyper::server::Response`.
|
||||
#[derive(Debug)]
|
||||
pub struct NewCompatService<S> {
|
||||
new_service: S
|
||||
}
|
||||
|
||||
pub fn new_service<S>(new_service: S) -> NewCompatService<S> {
|
||||
NewCompatService { new_service: new_service }
|
||||
}
|
||||
|
||||
impl<S, Bd> NewService for NewCompatService<S>
|
||||
where S: NewService<Request=http_types::Request<Body>, Response=http_types::Response<Bd>, Error=Error>
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response<Bd>;
|
||||
type Error = Error;
|
||||
type Instance = CompatService<S::Instance>;
|
||||
|
||||
fn new_service(&self) -> Result<Self::Instance, IoError> {
|
||||
self.new_service.new_service()
|
||||
.map(service)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,11 @@
|
||||
//! A `Server` is created to listen on a port, parse HTTP requests, and hand
|
||||
//! them off to a `Service`.
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
mod compat_impl;
|
||||
#[cfg(feature = "compat")]
|
||||
pub mod compat;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
@@ -16,6 +21,9 @@ use futures::task::{self, Task};
|
||||
use futures::{Future, Stream, Poll, Async, Sink, StartSend, AsyncSink};
|
||||
use futures::future::Map;
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
use http_types;
|
||||
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use tokio::reactor::{Core, Handle, Timeout};
|
||||
use tokio::net::TcpListener;
|
||||
@@ -27,6 +35,8 @@ pub use tokio_service::{NewService, Service};
|
||||
use http;
|
||||
use http::response;
|
||||
use http::request;
|
||||
#[cfg(feature = "compat")]
|
||||
use http::Body;
|
||||
|
||||
pub use http::response::Response;
|
||||
pub use http::request::Request;
|
||||
@@ -103,6 +113,18 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Bind a `NewService` using types from the `http` crate.
|
||||
///
|
||||
/// See `Http::bind`.
|
||||
#[cfg(feature = "compat")]
|
||||
pub fn bind_compat<S, Bd>(&self, addr: &SocketAddr, new_service: S) -> ::Result<Server<compat::NewCompatService<S>, Bd>>
|
||||
where S: NewService<Request = http_types::Request<Body>, Response = http_types::Response<Bd>, Error = ::Error> +
|
||||
Send + Sync + 'static,
|
||||
Bd: Stream<Item=B, Error=::Error>,
|
||||
{
|
||||
self.bind(addr, self::compat_impl::new_service(new_service))
|
||||
}
|
||||
|
||||
/// Use this `Http` instance to create a new server task which handles the
|
||||
/// connection `io` provided.
|
||||
///
|
||||
@@ -131,6 +153,25 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
||||
remote_addr: remote_addr,
|
||||
})
|
||||
}
|
||||
|
||||
/// Bind a `Service` using types from the `http` crate.
|
||||
///
|
||||
/// See `Http::bind_connection`.
|
||||
#[cfg(feature = "compat")]
|
||||
pub fn bind_connection_compat<S, I, Bd>(&self,
|
||||
handle: &Handle,
|
||||
io: I,
|
||||
remote_addr: SocketAddr,
|
||||
service: S)
|
||||
where S: Service<Request = http_types::Request<Body>, Response = http_types::Response<Bd>, Error = ::Error> + 'static,
|
||||
Bd: Stream<Item=B, Error=::Error> + 'static,
|
||||
I: AsyncRead + AsyncWrite + 'static,
|
||||
{
|
||||
self.bind_server(handle, io, HttpService {
|
||||
inner: compat_impl::service(service),
|
||||
remote_addr: remote_addr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> Clone for Http<B> {
|
||||
|
||||
Reference in New Issue
Block a user