use std::error::Error as StdError; use std::fmt; use std::marker::PhantomData; use futures::{future, Future, IntoFuture}; use body::Payload; use common::Never; use ::{Request, Response}; /// An asynchronous function from `Request` to `Response`. pub trait Service { /// The `Payload` body of the `http::Request`. type ReqBody: Payload; /// The `Payload` body of the `http::Response`. type ResBody: Payload; /// The error type that can occur within this `Service`. /// /// Note: Returning an `Error` to a hyper server will cause the connection /// to be abruptly aborted. In most cases, it is better to return a `Response` /// with a 4xx or 5xx status code. type Error: Into>; /// The `Future` returned by this `Service`. type Future: Future, Error=Self::Error>; /// Calls this `Service` with a request, returning a `Future` of the response. fn call(&mut self, req: Request) -> Self::Future; } /// Create a `Service` from a function. /// /// # Example /// /// ```rust /// use hyper::{Body, Request, Response, Version}; /// use hyper::service::service_fn; /// /// let service = service_fn(|req: Request| { /// if req.version() == Version::HTTP_11 { /// Ok(Response::new(Body::from("Hello World"))) /// } else { /// // Note: it's usually better to return a Response /// // with an appropriate StatusCode instead of an Err. /// Err("not HTTP/1.1, abort connection") /// } /// }); /// ``` pub fn service_fn(f: F) -> ServiceFn where F: Fn(Request) -> S, S: IntoFuture, { ServiceFn { f, _req: PhantomData, } } /// Create a `Service` from a function that never errors. /// /// # Example /// /// ```rust /// use hyper::{Body, Request, Response}; /// use hyper::service::service_fn_ok; /// /// let service = service_fn_ok(|req: Request| { /// println!("request: {} {}", req.method(), req.uri()); /// Response::new(Body::from("Hello World")) /// }); /// ``` pub fn service_fn_ok(f: F) -> ServiceFnOk where F: Fn(Request) -> Response, S: Payload, { ServiceFnOk { f, _req: PhantomData, } } // Not exported from crate as this will likely be replaced with `impl Service`. pub struct ServiceFn { f: F, _req: PhantomData, } impl Service for ServiceFn where F: Fn(Request) -> Ret, ReqBody: Payload, Ret: IntoFuture>, Ret::Error: Into>, ResBody: Payload, { type ReqBody = ReqBody; type ResBody = ResBody; type Error = Ret::Error; type Future = Ret::Future; fn call(&mut self, req: Request) -> Self::Future { (self.f)(req).into_future() } } impl IntoFuture for ServiceFn { type Future = future::FutureResult; type Item = Self; type Error = Never; fn into_future(self) -> Self::Future { future::ok(self) } } impl fmt::Debug for ServiceFn { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("impl Service") .finish() } } // Not exported from crate as this will likely be replaced with `impl Service`. pub struct ServiceFnOk { f: F, _req: PhantomData, } impl Service for ServiceFnOk where F: Fn(Request) -> Response, ReqBody: Payload, ResBody: Payload, { type ReqBody = ReqBody; type ResBody = ResBody; type Error = Never; type Future = future::FutureResult, Never>; fn call(&mut self, req: Request) -> Self::Future { future::ok((self.f)(req)) } } impl IntoFuture for ServiceFnOk { type Future = future::FutureResult; type Item = Self; type Error = Never; fn into_future(self) -> Self::Future { future::ok(self) } } impl fmt::Debug for ServiceFnOk { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("impl Service") .finish() } }