diff --git a/examples/hello.rs b/examples/hello.rs index d468a680ad..2286b60dc8 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -3,35 +3,23 @@ extern crate hyper; extern crate futures; extern crate pretty_env_logger; -use futures::future::FutureResult; - use hyper::header::{ContentLength, ContentType}; -use hyper::server::{Http, Service, Request, Response}; +use hyper::server::{Http, Response, const_service, service_fn}; static PHRASE: &'static [u8] = b"Hello World!"; -struct Hello; - -impl Service for Hello { - type Request = Request; - type Response = Response; - type Error = hyper::Error; - type Future = FutureResult; - fn call(&self, _req: Request) -> Self::Future { - futures::future::ok( - Response::new() - .with_header(ContentLength(PHRASE.len() as u64)) - .with_header(ContentType::plaintext()) - .with_body(PHRASE) - ) - } - -} - fn main() { pretty_env_logger::init().unwrap(); - let addr = "127.0.0.1:3000".parse().unwrap(); - let mut server = Http::new().bind(&addr, || Ok(Hello)).unwrap(); + let addr = ([127, 0, 0, 1], 3000).into(); + + let new_service = const_service(service_fn(|_| { + Ok(Response::::new() + .with_header(ContentLength(PHRASE.len() as u64)) + .with_header(ContentType::plaintext()) + .with_body(PHRASE)) + })); + + let mut server = Http::new().bind(&addr, new_service).unwrap(); server.no_proto(); println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap()); server.run().unwrap(); diff --git a/src/server/mod.rs b/src/server/mod.rs index fefda0ee65..5b1e083469 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -7,6 +7,7 @@ mod compat_impl; #[cfg(feature = "compat")] pub mod compat; +mod service; use std::cell::RefCell; use std::fmt; @@ -46,6 +47,8 @@ feat_server_proto! { }; } +pub use self::service::{const_service, service_fn}; + /// An instance of the HTTP protocol, and implementation of tokio-proto's /// `ServerProto` trait. /// diff --git a/src/server/service.rs b/src/server/service.rs new file mode 100644 index 0000000000..20c9812e35 --- /dev/null +++ b/src/server/service.rs @@ -0,0 +1,64 @@ +use std::marker::PhantomData; +use std::sync::Arc; + +use futures::IntoFuture; +use tokio_service::{NewService, Service}; + +/// Create a `Service` from a function. +pub fn service_fn(f: F) -> ServiceFn +where + F: Fn(R) -> S, + S: IntoFuture, +{ + ServiceFn { + f: f, + _req: PhantomData, + } +} + +/// Create a `NewService` by sharing references of `service. +pub fn const_service(service: S) -> ConstService { + ConstService { + svc: Arc::new(service), + } +} + +#[derive(Debug)] +pub struct ServiceFn { + f: F, + _req: PhantomData R>, +} + +impl Service for ServiceFn +where + F: Fn(R) -> S, + S: IntoFuture, +{ + type Request = R; + type Response = S::Item; + type Error = S::Error; + type Future = S::Future; + + fn call(&self, req: Self::Request) -> Self::Future { + (self.f)(req).into_future() + } +} + +#[derive(Debug)] +pub struct ConstService { + svc: Arc, +} + +impl NewService for ConstService +where + S: Service, +{ + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type Instance = Arc; + + fn new_service(&self) -> ::std::io::Result { + Ok(self.svc.clone()) + } +}