tower_web/routing/resource.rs
1use error;
2use response::Serializer;
3use routing::{RouteMatch, RouteSet};
4use util::BufStream;
5
6use bytes::Buf;
7use futures::{Future, Poll};
8use futures::future::FutureResult;
9use http;
10
11use std::marker::PhantomData;
12
13/// A `Resource` processes HTTP requests received by the service.
14///
15/// A single service is composed of one or more resources. A resource instance
16/// is created with a route set representing the set of routes that it is able
17/// to handle. The service merges the route sets together and uses it to match
18/// inbound requests.
19///
20/// When matching a route, the route set returns a `Self::Destination` value.
21/// This value is then provided to `Resource::dispatch` and this is how the
22/// resource instance knows which method to dispatch the request to.
23///
24/// Users are not expected to implement `Resource` themselves. Instead, the
25/// `impl_web!` macro will generate a `Resource` implementation. The
26/// implementation is then passed to `ServiceBuilder` to define the web service.
27pub trait Resource: Clone {
28 /// Token mapping a route to a resource method.
29 type Destination: Clone + Send + Sync + 'static;
30
31 /// The HTTP request body type.
32 type RequestBody: BufStream;
33
34 /// Buffer type yielded by the response body.
35 type Buf: Buf;
36
37 /// The HTTP response body type.
38 ///
39 /// This value will yield one or more `Self::Buf` values.
40 type Body: BufStream<Item = Self::Buf, Error = ::Error>;
41
42 /// Response future
43 type Future: ResourceFuture<Body = Self::Body>;
44
45 /// Process the HTTP request and return the response asynchronously.
46 ///
47 /// The HTTP request has already been matched against the route set before
48 /// calling this function. The `destination` and `route_match` arguments
49 /// provide the necessary context for the resource to process the matched
50 /// HTTP request.
51 fn dispatch(
52 &mut self,
53 destination: Self::Destination,
54 route_match: &RouteMatch,
55 body: Self::RequestBody,
56 ) -> Self::Future;
57}
58
59/// A specialized response future returned by resources.
60///
61/// The `ResourceFuture` allows passing the HTTP response into the future when
62/// polling.
63pub trait ResourceFuture {
64 /// HTTP response body type
65 type Body;
66
67 /// Attempt to resolve the response future to a final value.
68 fn poll_response(&mut self, request: &http::Request<()>)
69 -> Poll<http::Response<Self::Body>, ::Error>;
70}
71
72/// Convert a value into a `Resource`
73pub trait IntoResource<S, RequestBody>
74where S: Serializer,
75 RequestBody: BufStream,
76{
77 /// Token mapping a route to a resource method.
78 ///
79 /// This will always be set to the same type as
80 /// `Self::Resource::Destination`.
81 type Destination: Clone + Send + Sync + 'static;
82
83 /// The `Resource` value being converted to
84 type Resource: Resource<Destination = Self::Destination,
85 RequestBody = RequestBody>;
86
87 /// Returns the resource's set of routes.
88 fn routes(&self) -> RouteSet<Self::Destination>;
89
90 /// Convert `self` into a `Resource` value.
91 fn into_resource(self, serializer: S) -> Self::Resource;
92}
93
94impl<T, B> ResourceFuture for T
95where
96 T: Future<Item = http::Response<B>, Error = ::Error>
97{
98 type Body = B;
99
100 fn poll_response(&mut self, _: &http::Request<()>) -> Poll<T::Item, ::Error> {
101 self.poll()
102 }
103}
104
105/// A resource with no methods.
106///
107/// Attempting to route to this resource will result in a 404 response.
108#[derive(Debug)]
109pub struct Unit<B> {
110 _p: PhantomData<B>,
111}
112
113impl<B> Unit<B> {
114 /// Create a new `Unit` instance.
115 pub fn new() -> Self {
116 Unit { _p: PhantomData }
117 }
118}
119
120impl<B> Resource for Unit<B>
121where B: BufStream,
122{
123 type Destination = ();
124 type RequestBody = B;
125 type Buf = <Self::Body as BufStream>::Item;
126 type Body = error::Map<String>;
127 type Future = FutureResult<http::Response<Self::Body>, ::Error>;
128
129 fn dispatch(&mut self, _: (), _: &RouteMatch, _: Self::RequestBody) -> Self::Future {
130 unreachable!();
131 }
132}
133
134impl<B> Clone for Unit<B> {
135 fn clone(&self) -> Self {
136 Unit::new()
137 }
138}