tower_web/middleware/
middleware.rs

1use super::Chain;
2
3use tower_service::Service;
4
5/// Decorates a `Service`, transforming either the request or the response.
6///
7/// Often, many of the pieces needed for writing network applications can be
8/// reused across multiple services. The `Middleware` trait can be used to write
9/// reusable components that can be applied to very different kinds of services;
10/// for example, it can be applied to services operating on different protocols,
11/// and to both the client and server side of a network transaction.
12///
13/// # Log
14///
15/// Take request logging as an example:
16///
17/// ```rust
18/// # extern crate futures;
19/// # extern crate tower_service;
20/// # extern crate tower_web;
21/// # #[macro_use] extern crate log;
22/// use tower_service::Service;
23/// use tower_web::middleware::Middleware;
24/// use futures::{Future, Poll};
25///
26/// use std::fmt;
27///
28/// pub struct LogMiddleware {
29///     target: &'static str,
30/// }
31///
32/// impl<S> Middleware<S> for LogMiddleware
33/// where
34///     S: Service,
35///     S::Request: fmt::Debug,
36/// {
37///     type Request = S::Request;
38///     type Response = S::Response;
39///     type Error = S::Error;
40///     type Service = LogService<S>;
41///
42///     fn wrap(&self, service: S) -> LogService<S> {
43///         LogService {
44///             target: self.target,
45///             service
46///         }
47///     }
48/// }
49///
50/// // This service implements the Log behavior
51/// pub struct LogService<S> {
52///     target: &'static str,
53///     service: S,
54/// }
55///
56/// impl<S> Service for LogService<S>
57/// where
58///     S: Service,
59///     S::Request: fmt::Debug,
60/// {
61///     type Request = S::Request;
62///     type Response = S::Response;
63///     type Error = S::Error;
64///     type Future = S::Future;
65///
66///     fn poll_ready(&mut self) -> Poll<(), Self::Error> {
67///         self.service.poll_ready()
68///     }
69///
70///     fn call(&mut self, request: Self::Request) -> Self::Future {
71///         info!(target: self.target, "request = {:?}", request);
72///         self.service.call(request)
73///     }
74/// }
75/// ```
76///
77/// The above log implementation is decoupled from the underlying protocol and
78/// is also decoupled from client or server concerns. In other words, the same
79/// log middleware could be used in either a client or a server.
80pub trait Middleware<S> {
81    /// The wrapped service request type
82    type Request;
83
84    /// The wrapped service response type
85    type Response;
86
87    /// The wrapped service's error type
88    type Error;
89
90    /// The wrapped service
91    type Service: Service<Request = Self::Request,
92                         Response = Self::Response,
93                            Error = Self::Error>;
94
95    /// Wrap the given service with the middleware, returning a new service
96    /// that has been decorated with the middleware.
97    fn wrap(&self, inner: S) -> Self::Service;
98
99    /// Return a new `Middleware` instance that applies both `self` and
100    /// `middleware` to services being wrapped.
101    ///
102    /// This defines a middleware stack.
103    fn chain<T>(self, middleware: T) -> Chain<Self, T>
104    where T: Middleware<Self::Service>,
105          Self: Sized,
106    {
107        Chain::new(self, middleware)
108    }
109}