rocket/route/
handler.rs

1use crate::{Request, Data};
2use crate::response::{Response, Responder};
3use crate::http::Status;
4
5/// Type alias for the return type of a [`Route`](crate::Route)'s
6/// [`Handler::handle()`].
7pub type Outcome<'r> = crate::outcome::Outcome<Response<'r>, Status, (Data<'r>, Status)>;
8
9/// Type alias for the return type of a _raw_ [`Route`](crate::Route)'s
10/// [`Handler`].
11pub type BoxFuture<'r, T = Outcome<'r>> = futures::future::BoxFuture<'r, T>;
12
13/// Trait implemented by [`Route`](crate::Route) request handlers.
14///
15/// In general, you will never need to implement `Handler` manually or be
16/// concerned about the `Handler` trait; Rocket's code generation handles
17/// everything for you. You only need to learn about this trait if you want to
18/// provide an external, library-based mechanism to handle requests where
19/// request handling depends on input from the user. In other words, if you want
20/// to write a plugin for Rocket that looks mostly like a static route but need
21/// user provided state to make a request handling decision, you should consider
22/// implementing a custom `Handler`.
23///
24/// ## Async Trait
25///
26/// This is an _async_ trait. Implementations must be decorated
27/// [`#[rocket::async_trait]`](crate::async_trait).
28///
29/// # Example
30///
31/// Say you'd like to write a handler that changes its functionality based on an
32/// enum value that the user provides:
33///
34/// ```rust
35/// #[derive(Copy, Clone)]
36/// enum Kind {
37///     Simple,
38///     Intermediate,
39///     Complex,
40/// }
41/// ```
42///
43/// Such a handler might be written and used as follows:
44///
45/// ```rust,no_run
46/// # #[derive(Copy, Clone)] enum Kind { Simple, Intermediate, Complex, }
47/// use rocket::{Request, Data};
48/// use rocket::route::{Handler, Route, Outcome};
49/// use rocket::http::Method;
50///
51/// #[derive(Clone)]
52/// struct CustomHandler(Kind);
53///
54/// #[rocket::async_trait]
55/// impl Handler for CustomHandler {
56///     async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r> {
57///         match self.0 {
58///             Kind::Simple => Outcome::from(req, "simple"),
59///             Kind::Intermediate => Outcome::from(req, "intermediate"),
60///             Kind::Complex => Outcome::from(req, "complex"),
61///         }
62///     }
63/// }
64///
65/// impl Into<Vec<Route>> for CustomHandler {
66///     fn into(self) -> Vec<Route> {
67///         vec![Route::new(Method::Get, "/", self)]
68///     }
69/// }
70///
71/// #[rocket::launch]
72/// fn rocket() -> _ {
73///     rocket::build().mount("/", CustomHandler(Kind::Simple))
74/// }
75/// ```
76///
77/// Note the following:
78///
79///   1. `CustomHandler` implements `Clone`. This is required so that
80///      `CustomHandler` implements `Cloneable` automatically. The `Cloneable`
81///      trait serves no other purpose but to ensure that every `Handler` can be
82///      cloned, allowing `Route`s to be cloned.
83///   2. `CustomHandler` implements `Into<Vec<Route>>`, allowing an instance to
84///      be used directly as the second parameter to `rocket.mount()`.
85///   3. Unlike static-function-based handlers, this custom handler can make use
86///      of any internal state.
87///
88/// # Alternatives
89///
90/// The previous example could have been implemented using a combination of
91/// managed state and a static route, as follows:
92///
93/// ```rust,no_run
94/// # #[macro_use] extern crate rocket;
95/// #
96/// # #[derive(Copy, Clone)]
97/// # enum Kind {
98/// #     Simple,
99/// #     Intermediate,
100/// #     Complex,
101/// # }
102/// #
103/// use rocket::State;
104///
105/// #[get("/")]
106/// fn custom_handler(state: &State<Kind>) -> &'static str {
107///     match state.inner() {
108///         Kind::Simple => "simple",
109///         Kind::Intermediate => "intermediate",
110///         Kind::Complex => "complex",
111///     }
112/// }
113///
114/// #[launch]
115/// fn rocket() -> _ {
116///     rocket::build()
117///         .mount("/", routes![custom_handler])
118///         .manage(Kind::Simple)
119/// }
120/// ```
121///
122/// Pros:
123///
124///   * The handler is easier to implement since Rocket's code generation
125///     ensures type-safety at all levels.
126///
127/// Cons:
128///
129///   * Only one `Kind` can be stored in managed state. As such, only one
130///     variant of the custom handler can be used.
131///   * The user must remember to manually call `rocket.manage(state)`.
132///
133/// Use this alternative when a single configuration is desired and your custom
134/// handler is private to your application. For all other cases, a custom
135/// `Handler` implementation is preferred.
136#[crate::async_trait]
137pub trait Handler: Cloneable + Send + Sync + 'static {
138    /// Called by Rocket when a `Request` with its associated `Data` should be
139    /// handled by this handler.
140    ///
141    /// The variant of `Outcome` returned by the returned `Future` determines
142    /// what Rocket does next. If the return value is a `Success(Response)`, the
143    /// wrapped `Response` is used to respond to the client. If the return value
144    /// is an `Error(Status)`, the error catcher for `Status` is invoked to
145    /// generate a response. Otherwise, if the return value is `Forward(Data)`,
146    /// the next matching route is attempted. If there are no other matching
147    /// routes, the `404` error catcher is invoked.
148    async fn handle<'r>(&self, request: &'r Request<'_>, data: Data<'r>) -> Outcome<'r>;
149}
150
151// We write this manually to avoid double-boxing.
152impl<F: Clone + Sync + Send + 'static> Handler for F
153    where for<'x> F: Fn(&'x Request<'_>, Data<'x>) -> BoxFuture<'x>,
154{
155    #[inline(always)]
156    fn handle<'r, 'life0, 'life1, 'async_trait>(
157        &'life0 self,
158        req: &'r Request<'life1>,
159        data: Data<'r>,
160    ) -> BoxFuture<'r>
161        where 'r: 'async_trait,
162              'life0: 'async_trait,
163              'life1: 'async_trait,
164              Self: 'async_trait,
165    {
166        self(req, data)
167    }
168}
169
170// FIXME!
171impl<'r, 'o: 'r> Outcome<'o> {
172    /// Return the `Outcome` of response to `req` from `responder`.
173    ///
174    /// If the responder returns `Ok`, an outcome of `Success` is returned with
175    /// the response. If the responder returns `Err`, an outcome of `Error` is
176    /// returned with the status code.
177    ///
178    /// # Example
179    ///
180    /// ```rust
181    /// use rocket::{Request, Data, route};
182    ///
183    /// fn str_responder<'r>(req: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
184    ///     route::Outcome::from(req, "Hello, world!")
185    /// }
186    /// ```
187    #[inline]
188    pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {
189        match responder.respond_to(req) {
190            Ok(response) => Outcome::Success(response),
191            Err(status) => Outcome::Error(status)
192        }
193    }
194
195    /// Return the `Outcome` of response to `req` from `responder`.
196    ///
197    /// If the responder returns `Ok`, an outcome of `Success` is returned with
198    /// the response. If the responder returns `Err`, an outcome of `Error` is
199    /// returned with the status code.
200    ///
201    /// # Example
202    ///
203    /// ```rust
204    /// use rocket::{Request, Data, route};
205    ///
206    /// fn str_responder<'r>(req: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
207    ///     route::Outcome::from(req, "Hello, world!")
208    /// }
209    /// ```
210    #[inline]
211    pub fn try_from<R, E>(req: &'r Request<'_>, result: Result<R, E>) -> Outcome<'r>
212        where R: Responder<'r, 'o>, E: std::fmt::Debug
213    {
214        let responder = result.map_err(crate::response::Debug);
215        match responder.respond_to(req) {
216            Ok(response) => Outcome::Success(response),
217            Err(status) => Outcome::Error(status)
218        }
219    }
220
221    /// Return an `Outcome` of `Error` with the status code `code`. This is
222    /// equivalent to `Outcome::Error(code)`.
223    ///
224    /// This method exists to be used during manual routing.
225    ///
226    /// # Example
227    ///
228    /// ```rust
229    /// use rocket::{Request, Data, route};
230    /// use rocket::http::Status;
231    ///
232    /// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
233    ///     route::Outcome::error(Status::BadRequest)
234    /// }
235    /// ```
236    #[inline(always)]
237    pub fn error(code: Status) -> Outcome<'r> {
238        Outcome::Error(code)
239    }
240
241    /// Return an `Outcome` of `Forward` with the data `data` and status
242    /// `status`. This is equivalent to `Outcome::Forward((data, status))`.
243    ///
244    /// This method exists to be used during manual routing.
245    ///
246    /// # Example
247    ///
248    /// ```rust
249    /// use rocket::{Request, Data, route};
250    /// use rocket::http::Status;
251    ///
252    /// fn always_forward<'r>(_: &'r Request, data: Data<'r>) -> route::Outcome<'r> {
253    ///     route::Outcome::forward(data, Status::InternalServerError)
254    /// }
255    /// ```
256    #[inline(always)]
257    pub fn forward(data: Data<'r>, status: Status) -> Outcome<'r> {
258        Outcome::Forward((data, status))
259    }
260}
261
262// INTERNAL: A handler to use when one is needed temporarily.
263#[doc(hidden)]
264pub fn dummy_handler<'r>(r: &'r Request<'_>, _: Data<'r>) -> BoxFuture<'r> {
265    Outcome::from(r, ()).pin()
266}
267
268mod private {
269    pub trait Sealed {}
270    impl<T: super::Handler + Clone> Sealed for T {}
271}
272
273/// Helper trait to make a [`Route`](crate::Route)'s `Box<dyn Handler>`
274/// `Clone`.
275///
276/// This trait cannot be implemented directly. Instead, implement `Clone` and
277/// [`Handler`]; all types that implement `Clone` and `Handler` automatically
278/// implement `Cloneable`.
279pub trait Cloneable: private::Sealed {
280    #[doc(hidden)]
281    fn clone_handler(&self) -> Box<dyn Handler>;
282}
283
284impl<T: Handler + Clone> Cloneable for T {
285    fn clone_handler(&self) -> Box<dyn Handler> {
286        Box::new(self.clone())
287    }
288}
289
290impl Clone for Box<dyn Handler> {
291    fn clone(&self) -> Box<dyn Handler> {
292        self.clone_handler()
293    }
294}