rocket/response/
responder.rs

1use std::fs::File;
2use std::io::Cursor;
3use std::sync::Arc;
4
5use crate::http::{Status, ContentType, StatusClass};
6use crate::response::{self, Response};
7use crate::request::Request;
8
9/// Trait implemented by types that generate responses for clients.
10///
11/// Any type that implements `Responder` can be used as the return type of a
12/// handler:
13///
14/// ```rust
15/// # #[macro_use] extern crate rocket;
16/// # type T = ();
17/// #
18/// // This works for any `T` that implements `Responder`.
19/// #[get("/")]
20/// fn index() -> T { /* ... */ }
21/// ```
22///
23/// # Deriving
24///
25/// This trait can, and largely _should_, be automatically derived. The derive
26/// can handle all simple cases and most complex cases, too. When deriving
27/// `Responder`, the first field of the annotated structure (or of each variant
28/// if an `enum`) is used to generate a response while the remaining fields are
29/// used as response headers:
30///
31/// ```rust
32/// # #[macro_use] extern crate rocket;
33/// # #[cfg(feature = "json")] mod _main {
34/// # type Template = String;
35/// use rocket::http::ContentType;
36/// use rocket::serde::{Serialize, json::Json};
37///
38/// #[derive(Responder)]
39/// enum Error<T> {
40///     #[response(status = 400)]
41///     Unauthorized(Json<T>),
42///     #[response(status = 404)]
43///     NotFound(Template, ContentType),
44/// }
45/// # }
46/// ```
47///
48/// For full details on deriving `Responder`, see the [`Responder` derive].
49///
50/// [`Responder` derive]: derive@crate::Responder
51///
52/// # Provided Implementations
53///
54/// Rocket implements `Responder` for several standard library types. Their
55/// behavior is documented here. Note that the `Result` implementation is
56/// overloaded, allowing for two `Responder`s to be used at once, depending on
57/// the variant.
58///
59///   * **&str**
60///
61///     Sets the `Content-Type` to `text/plain`. The string is used as the body
62///     of the response, which is fixed size and not streamed. To stream a raw
63///     string, use `Stream::from(Cursor::new(string))`.
64///
65///   * **String**
66///
67///     Sets the `Content-Type` to `text/plain`. The string is used as the body
68///     of the response, which is fixed size and not streamed. To stream a
69///     string, use `Stream::from(Cursor::new(string))`.
70///
71///   * **&\[u8\]**
72///
73///     Sets the `Content-Type` to `application/octet-stream`. The slice
74///     is used as the body of the response, which is fixed size and not
75///     streamed. To stream a slice of bytes, use
76///     `Stream::from(Cursor::new(data))`.
77///
78///   * **Vec&lt;u8>**
79///
80///     Sets the `Content-Type` to `application/octet-stream`. The vector's data
81///     is used as the body of the response, which is fixed size and not
82///     streamed. To stream a vector of bytes, use
83///     `Stream::from(Cursor::new(vec))`.
84///
85///   * **File**
86///
87///     Responds with a streamed body containing the data in the `File`. No
88///     `Content-Type` is set. To automatically have a `Content-Type` set based
89///     on the file's extension, use [`NamedFile`](crate::fs::NamedFile).
90///
91///   * **()**
92///
93///     Responds with an empty body. No `Content-Type` is set.
94///
95///   * **Option&lt;T>**
96///
97///     If the `Option` is `Some`, the wrapped responder is used to respond to
98///     the client. Otherwise, an `Err` with status **404 Not Found** is
99///     returned and a warning is printed to the console.
100///
101///   * **Result&lt;T, E>**
102///
103///     If the `Result` is `Ok`, the wrapped `Ok` responder is used to respond
104///     to the client. If the `Result` is `Err`, the wrapped `Err` responder is
105///     used to respond to the client.
106///
107/// # Return Value
108///
109/// A `Responder` returns a `Result<Response, Status>`.
110///
111///   * An `Ok(Response)` indicates success. The `Response` will be written out
112///     to the client.
113///
114///   * An `Err(Status)` indicates an error. The error catcher for `Status` will
115///     be invoked to generate a response.
116///
117/// # Implementation Tips
118///
119/// This section describes a few best practices to take into account when
120/// implementing `Responder`.
121///
122/// 1. Avoid Manual Implementations
123///
124///    The [`Responder` derive] is a powerful mechanism that eliminates the need
125///    to implement `Responder` in almost all cases. We encourage you to explore
126///    using the derive _before_ attempting to implement `Responder` directly.
127///    It allows you to leverage existing `Responder` implementations through
128///    composition, decreasing the opportunity for mistakes or performance
129///    degradation.
130///
131/// 2. Joining and Merging
132///
133///    When chaining/wrapping other `Responder`s, start with
134///    [`Response::build_from()`] and/or use the [`merge()`](Response::merge())
135///    or [`join()`](Response::join()) methods on the `Response` or
136///    `ResponseBuilder` struct. Ensure that you document merging or joining
137///    behavior appropriately.
138///
139/// 3. Inspecting Requests
140///
141///    While tempting, a `Responder` that varies its functionality based on the
142///    incoming request sacrifices its functionality being understood based
143///    purely on its type. By implication, gleaning the functionality of a
144///    _handler_ from its type signature also becomes more difficult. You should
145///    avoid varying responses based on the `Request` value as much as possible.
146///
147/// 4. Perform `async` I/O in Constructors
148///
149///    The `Responder` trait is not an `async` trait. This is not an oversight.
150///    Instead of performing `async` operations in what would be the
151///    `respond_to` method, perform them in a constructor for the responder. As
152///    an example, see [`NamedFile::open()`](crate::fs::NamedFile::open()),
153///    which performs the requisite I/O for `NamedFile`'s responder.
154///
155/// ## Lifetimes
156///
157/// `Responder` has two lifetimes: `Responder<'r, 'o: 'r>`.
158///
159///   * `'r` bounds the reference to the `&'r Request`.
160///
161///   * `'o` bounds the returned `Response<'o>` to values that live at least as
162///     long as the request.
163///
164///     This includes borrows from the `Request` itself (where `'o` would be
165///     `'r` as in `impl<'r> Responder<'r, 'r>`) as well as `'static` data
166///     (where `'o` would be `'static` as in `impl<'r> Responder<'r, 'static>`).
167///
168/// In practice, you are likely choosing between four signatures:
169///
170/// ```rust
171/// # use rocket::request::Request;
172/// # use rocket::response::{self, Responder};
173/// # struct A;
174/// // If the response contains no borrowed data.
175/// impl<'r> Responder<'r, 'static> for A {
176///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
177///         todo!()
178///     }
179/// }
180///
181/// # struct B<'r>(&'r str);
182/// // If the response borrows from the request.
183/// impl<'r> Responder<'r, 'r> for B<'r> {
184///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {
185///         todo!()
186///     }
187/// }
188///
189/// # struct C;
190/// // If the response is or wraps a borrow that may outlive the request.
191/// impl<'r, 'o: 'r> Responder<'r, 'o> for &'o C {
192///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
193///         todo!()
194///     }
195/// }
196///
197/// # struct D<R>(R);
198/// // If the response wraps an existing responder.
199/// impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for D<R> {
200///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
201///         todo!()
202///     }
203/// }
204/// ```
205///
206/// # Example
207///
208/// Say that you have a custom type, `Person`:
209///
210/// ```rust
211/// struct Person {
212///     name: String,
213///     age: u16
214/// }
215/// ```
216///
217/// You'd like to use `Person` as a `Responder` so that you can return a
218/// `Person` directly from a handler:
219///
220/// ```rust
221/// # #[macro_use] extern crate rocket;
222/// # type Person = String;
223/// #[get("/person/<id>")]
224/// fn person(id: usize) -> Option<Person> {
225///     # /*
226///     Person::from_id(id)
227///     # */ None
228/// }
229/// # fn main() {}
230/// ```
231///
232/// You want the `Person` responder to set two header fields: `X-Person-Name`
233/// and `X-Person-Age` as well as supply a custom representation of the object
234/// (`Content-Type: application/x-person`) in the body of the response. The
235/// following `Responder` implementation accomplishes this:
236///
237/// ```rust
238/// # #[macro_use] extern crate rocket;
239/// #
240/// # #[derive(Debug)]
241/// # struct Person { name: String, age: u16 }
242/// #
243/// use std::io::Cursor;
244///
245/// use rocket::request::Request;
246/// use rocket::response::{self, Response, Responder};
247/// use rocket::http::ContentType;
248///
249/// impl<'r> Responder<'r, 'static> for Person {
250///     fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
251///         let string = format!("{}:{}", self.name, self.age);
252///         Response::build_from(string.respond_to(req)?)
253///             .raw_header("X-Person-Name", self.name)
254///             .raw_header("X-Person-Age", self.age.to_string())
255///             .header(ContentType::new("application", "x-person"))
256///             .ok()
257///     }
258/// }
259/// #
260/// # #[get("/person")]
261/// # fn person() -> Person { Person { name: "a".to_string(), age: 20 } }
262/// # fn main() {  }
263/// ```
264///
265/// Note that the implementation could have instead been derived if structured
266/// in a slightly different manner:
267///
268/// ```rust
269/// use rocket::http::Header;
270/// use rocket::response::Responder;
271///
272/// #[derive(Responder)]
273/// #[response(content_type = "application/x-person")]
274/// struct Person {
275///     text: String,
276///     name: Header<'static>,
277///     age: Header<'static>,
278/// }
279///
280/// impl Person {
281///     fn new(name: &str, age: usize) -> Person {
282///         Person {
283///             text: format!("{}:{}", name, age),
284///             name: Header::new("X-Person-Name", name.to_string()),
285///             age: Header::new("X-Person-Age", age.to_string())
286///         }
287///     }
288/// }
289/// #
290/// # #[rocket::get("/person")]
291/// # fn person() -> Person { Person::new("Bob", 29) }
292/// ```
293pub trait Responder<'r, 'o: 'r> {
294    /// Returns `Ok` if a `Response` could be generated successfully. Otherwise,
295    /// returns an `Err` with a failing `Status`.
296    ///
297    /// The `request` parameter is the `Request` that this `Responder` is
298    /// responding to.
299    ///
300    /// When using Rocket's code generation, if an `Ok(Response)` is returned,
301    /// the response will be written out to the client. If an `Err(Status)` is
302    /// returned, the error catcher for the given status is retrieved and called
303    /// to generate a final error response, which is then written out to the
304    /// client.
305    fn respond_to(self, request: &'r Request<'_>) -> response::Result<'o>;
306}
307
308/// Returns a response with Content-Type `text/plain` and a fixed-size body
309/// containing the string `self`. Always returns `Ok`.
310impl<'r, 'o: 'r> Responder<'r, 'o> for &'o str {
311    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
312        Response::build()
313            .header(ContentType::Plain)
314            .sized_body(self.len(), Cursor::new(self))
315            .ok()
316    }
317}
318
319/// Returns a response with Content-Type `text/plain` and a fixed-size body
320/// containing the string `self`. Always returns `Ok`.
321impl<'r> Responder<'r, 'static> for String {
322    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
323        Response::build()
324            .header(ContentType::Plain)
325            .sized_body(self.len(), Cursor::new(self))
326            .ok()
327    }
328}
329
330#[repr(transparent)]
331struct DerefRef<T>(T);
332
333impl<T: std::ops::Deref> AsRef<[u8]> for DerefRef<T> where T::Target: AsRef<[u8]> {
334    fn as_ref(&self) -> &[u8] {
335        self.0.deref().as_ref()
336    }
337}
338
339/// Returns a response with Content-Type `text/plain` and a fixed-size body
340/// containing the string `self`. Always returns `Ok`.
341impl<'r> Responder<'r, 'static> for Arc<str> {
342    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
343        Response::build()
344            .header(ContentType::Plain)
345            .sized_body(self.len(), Cursor::new(DerefRef(self)))
346            .ok()
347    }
348}
349
350/// Returns a response with Content-Type `text/plain` and a fixed-size body
351/// containing the string `self`. Always returns `Ok`.
352impl<'r> Responder<'r, 'static> for Box<str> {
353    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
354        Response::build()
355            .header(ContentType::Plain)
356            .sized_body(self.len(), Cursor::new(DerefRef(self)))
357            .ok()
358    }
359}
360
361/// Returns a response with Content-Type `application/octet-stream` and a
362/// fixed-size body containing the data in `self`. Always returns `Ok`.
363impl<'r, 'o: 'r> Responder<'r, 'o> for &'o [u8] {
364    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
365        Response::build()
366            .header(ContentType::Binary)
367            .sized_body(self.len(), Cursor::new(self))
368            .ok()
369    }
370}
371
372/// Returns a response with Content-Type `application/octet-stream` and a
373/// fixed-size body containing the data in `self`. Always returns `Ok`.
374impl<'r> Responder<'r, 'static> for Vec<u8> {
375    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
376        Response::build()
377            .header(ContentType::Binary)
378            .sized_body(self.len(), Cursor::new(self))
379            .ok()
380    }
381}
382
383/// Returns a response with Content-Type `application/octet-stream` and a
384/// fixed-size body containing the data in `self`. Always returns `Ok`.
385impl<'r> Responder<'r, 'static> for Arc<[u8]> {
386    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
387        Response::build()
388            .header(ContentType::Binary)
389            .sized_body(self.len(), Cursor::new(self))
390            .ok()
391    }
392}
393
394/// Returns a response with Content-Type `application/octet-stream` and a
395/// fixed-size body containing the data in `self`. Always returns `Ok`.
396impl<'r> Responder<'r, 'static> for Box<[u8]> {
397    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
398        Response::build()
399            .header(ContentType::Binary)
400            .sized_body(self.len(), Cursor::new(self))
401            .ok()
402    }
403}
404
405/// Returns the response generated by the inner `T`. Note that this explicitly
406/// does not support `Box<dyn Responder>`.
407///
408/// ```rust,compile_fail
409/// #[macro_use] extern crate rocket;
410///
411/// use rocket::response::Responder;
412///
413/// #[get("/")]
414/// fn f() -> Box<dyn Responder<'static,'static>> {
415///     Box::new(())
416/// }
417/// ```
418///
419/// However, this `impl` allows boxing sized responders:
420///
421/// ```rust
422/// #[macro_use] extern crate rocket;
423///
424/// #[derive(Responder)]
425/// enum Content {
426///     Redirect(Box<rocket::response::Redirect>),
427///     Text(String),
428/// }
429///
430/// #[get("/")]
431/// fn f() -> Option<Box<String>> {
432///     None
433/// }
434///
435/// #[get("/")]
436/// fn g() -> Content {
437///     Content::Text("hello".to_string())
438/// }
439/// ```
440impl<'r, 'o: 'r, T: Responder<'r, 'o> + Sized> Responder<'r, 'o> for Box<T> {
441    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
442        let inner = *self;
443        inner.respond_to(req)
444    }
445}
446
447/// Returns a response with a sized body for the file. Always returns `Ok`.
448impl<'r> Responder<'r, 'static> for File {
449    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
450        tokio::fs::File::from(self).respond_to(req)
451    }
452}
453
454/// Returns a response with a sized body for the file. Always returns `Ok`.
455impl<'r> Responder<'r, 'static> for tokio::fs::File {
456    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
457        Response::build().sized_body(None, self).ok()
458    }
459}
460
461/// Returns an empty, default `Response`. Always returns `Ok`.
462impl<'r> Responder<'r, 'static> for () {
463    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
464        Ok(Response::new())
465    }
466}
467
468/// Responds with the inner `Responder` in `Cow`.
469impl<'r, 'o: 'r, R: ?Sized + ToOwned> Responder<'r, 'o> for std::borrow::Cow<'o, R>
470    where &'o R: Responder<'r, 'o> + 'o, <R as ToOwned>::Owned: Responder<'r, 'o> + 'r
471{
472    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
473        match self {
474            std::borrow::Cow::Borrowed(b) => b.respond_to(req),
475            std::borrow::Cow::Owned(o) => o.respond_to(req),
476        }
477    }
478}
479
480/// If `self` is `Some`, responds with the wrapped `Responder`. Otherwise prints
481/// a warning message and returns an `Err` of `Status::NotFound`.
482impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Option<R> {
483    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
484        match self {
485            Some(r) => r.respond_to(req),
486            None => {
487                warn_!("Response was `None`.");
488                Err(Status::NotFound)
489            },
490        }
491    }
492}
493
494/// Responds with the wrapped `Responder` in `self`, whether it is `Ok` or
495/// `Err`.
496impl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for Result<T, E>
497    where T: Responder<'r, 't>, E: Responder<'r, 'e>
498{
499    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
500        match self {
501            Ok(responder) => responder.respond_to(req),
502            Err(responder) => responder.respond_to(req),
503        }
504    }
505}
506
507/// Responds with the wrapped `Responder` in `self`, whether it is `Left` or
508/// `Right`.
509impl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for crate::Either<T, E>
510    where T: Responder<'r, 't>, E: Responder<'r, 'e>
511{
512    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
513        match self {
514            crate::Either::Left(r) => r.respond_to(req),
515            crate::Either::Right(r) => r.respond_to(req),
516        }
517    }
518}
519
520/// The response generated by `Status` depends on the status code itself. The
521/// table below summarizes the functionality:
522///
523/// | Status Code Range | Response                              |
524/// |-------------------|---------------------------------------|
525/// | [400, 599]        | Forwards to catcher for given status. |
526/// | 100, [200, 205]   | Empty with status of `self`.          |
527/// | All others.       | Invalid. Errors to `500` catcher.     |
528///
529/// In short, a client or server error status codes will forward to the
530/// corresponding error catcher, a successful status code less than `206` or
531/// `100` responds with any empty body and the given status code, and all other
532/// status code emit an error message and forward to the `500` (internal server
533/// error) catcher.
534impl<'r> Responder<'r, 'static> for Status {
535    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
536        match self.class() {
537            StatusClass::ClientError | StatusClass::ServerError => Err(self),
538            StatusClass::Success if self.code < 206 => {
539                Response::build().status(self).ok()
540            }
541            StatusClass::Informational if self.code == 100 => {
542                Response::build().status(self).ok()
543            }
544            _ => {
545                error_!("Invalid status used as responder: {}.", self);
546                Err(Status::InternalServerError)
547            }
548        }
549    }
550}