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}