feat(server): add const_service and service_fn helpers
				
					
				
			- `const_service` creates a `NewService` that clones references to the wrapped service. - `service_fn` creates a `Service` from a function. Useful with closures.
This commit is contained in:
		| @@ -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<Response, hyper::Error>; | ||||
|     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::<hyper::Body>::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(); | ||||
|   | ||||
| @@ -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. | ||||
| /// | ||||
|   | ||||
							
								
								
									
										64
									
								
								src/server/service.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/server/service.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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, R, S>(f: F) -> ServiceFn<F, R> | ||||
| where | ||||
|     F: Fn(R) -> S, | ||||
|     S: IntoFuture, | ||||
| { | ||||
|     ServiceFn { | ||||
|         f: f, | ||||
|         _req: PhantomData, | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Create a `NewService` by sharing references of `service. | ||||
| pub fn const_service<S>(service: S) -> ConstService<S> { | ||||
|     ConstService { | ||||
|         svc: Arc::new(service), | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct ServiceFn<F, R> { | ||||
|     f: F, | ||||
|     _req: PhantomData<fn() -> R>, | ||||
| } | ||||
|  | ||||
| impl<F, R, S> Service for ServiceFn<F, R> | ||||
| 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<S> { | ||||
|     svc: Arc<S>, | ||||
| } | ||||
|  | ||||
| impl<S> NewService for ConstService<S> | ||||
| where | ||||
|     S: Service, | ||||
| { | ||||
|     type Request = S::Request; | ||||
|     type Response = S::Response; | ||||
|     type Error = S::Error; | ||||
|     type Instance = Arc<S>; | ||||
|  | ||||
|     fn new_service(&self) -> ::std::io::Result<Self::Instance> { | ||||
|         Ok(self.svc.clone()) | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user