| use std::error::Error as StdError; |
| use std::fmt; |
| use std::marker::PhantomData; |
| |
| use futures::{future, Async, Future, IntoFuture, Poll}; |
| |
| 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<Box<dyn StdError + Send + Sync>>; |
| |
| /// The `Future` returned by this `Service`. |
| type Future: Future<Item=Response<Self::ResBody>, Error=Self::Error>; |
| |
| /// Returns `Ready` when the service is able to process requests. |
| /// |
| /// The implementation of this method is allowed to return a `Ready` even if |
| /// the service is not ready to process. In this case, the future returned |
| /// from `call` will resolve to an error. |
| fn poll_ready(&mut self) -> Poll<(), Self::Error> { |
| Ok(Async::Ready(())) |
| } |
| |
| /// Calls this `Service` with a request, returning a `Future` of the response. |
| fn call(&mut self, req: Request<Self::ReqBody>) -> 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<Body>| { |
| /// 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, R, S>(f: F) -> ServiceFn<F, R> |
| where |
| F: FnMut(Request<R>) -> 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<Body>| { |
| /// println!("request: {} {}", req.method(), req.uri()); |
| /// Response::new(Body::from("Hello World")) |
| /// }); |
| /// ``` |
| pub fn service_fn_ok<F, R, S>(f: F) -> ServiceFnOk<F, R> |
| where |
| F: FnMut(Request<R>) -> Response<S>, |
| S: Payload, |
| { |
| ServiceFnOk { |
| f, |
| _req: PhantomData, |
| } |
| } |
| |
| // Not exported from crate as this will likely be replaced with `impl Service`. |
| pub struct ServiceFn<F, R> { |
| f: F, |
| _req: PhantomData<fn(R)>, |
| } |
| |
| impl<F, ReqBody, Ret, ResBody> Service for ServiceFn<F, ReqBody> |
| where |
| F: FnMut(Request<ReqBody>) -> Ret, |
| ReqBody: Payload, |
| Ret: IntoFuture<Item=Response<ResBody>>, |
| Ret::Error: Into<Box<dyn StdError + Send + Sync>>, |
| ResBody: Payload, |
| { |
| type ReqBody = ReqBody; |
| type ResBody = ResBody; |
| type Error = Ret::Error; |
| type Future = Ret::Future; |
| |
| fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future { |
| (self.f)(req).into_future() |
| } |
| } |
| |
| impl<F, R> IntoFuture for ServiceFn<F, R> { |
| type Future = future::FutureResult<Self::Item, Self::Error>; |
| type Item = Self; |
| type Error = Never; |
| |
| fn into_future(self) -> Self::Future { |
| future::ok(self) |
| } |
| } |
| |
| impl<F, R> fmt::Debug for ServiceFn<F, R> { |
| 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, R> { |
| f: F, |
| _req: PhantomData<fn(R)>, |
| } |
| |
| impl<F, ReqBody, ResBody> Service for ServiceFnOk<F, ReqBody> |
| where |
| F: FnMut(Request<ReqBody>) -> Response<ResBody>, |
| ReqBody: Payload, |
| ResBody: Payload, |
| { |
| type ReqBody = ReqBody; |
| type ResBody = ResBody; |
| type Error = Never; |
| type Future = future::FutureResult<Response<ResBody>, Never>; |
| |
| fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future { |
| future::ok((self.f)(req)) |
| } |
| } |
| |
| impl<F, R> IntoFuture for ServiceFnOk<F, R> { |
| type Future = future::FutureResult<Self::Item, Self::Error>; |
| type Item = Self; |
| type Error = Never; |
| |
| fn into_future(self) -> Self::Future { |
| future::ok(self) |
| } |
| } |
| |
| impl<F, R> fmt::Debug for ServiceFnOk<F, R> { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| f.debug_struct("impl Service") |
| .finish() |
| } |
| } |
| |
| //#[cfg(test)] |
| fn _assert_fn_mut() { |
| fn assert_service<T: Service>(_t: &T) {} |
| |
| let mut val = 0; |
| |
| let svc = service_fn(move |_req: Request<::Body>| { |
| val += 1; |
| future::ok::<_, Never>(Response::new(::Body::empty())) |
| }); |
| |
| assert_service(&svc); |
| |
| let svc = service_fn_ok(move |_req: Request<::Body>| { |
| val += 1; |
| Response::new(::Body::empty()) |
| }); |
| |
| assert_service(&svc); |
| } |