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<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<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<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}