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