rocket/response/
content.rs

1//! Contains types that set the Content-Type of a response.
2//!
3//! # Usage
4//!
5//! Each type in this module is a `Responder` that wraps an existing
6//! `Responder`, overwriting the `Content-Type` of the response but otherwise
7//! delegating the response to the wrapped responder. As a convenience,
8//! `(ContentType, R)` where `R: Responder` is _also_ a `Responder` that
9//! overrides the `Content-Type` to the value in `.0`:
10//!
11//! ```rust
12//! # use rocket::get;
13//! use rocket::http::ContentType;
14//!
15//! #[get("/")]
16//! fn index() -> (ContentType, &'static str) {
17//!     (ContentType::HTML, "Is this HTML? <p>Sure, why not!</p>")
18//! }
19//! ```
20//!
21//! # Example
22//!
23//! The following snippet creates a `RawHtml` response from a string. Normally,
24//! raw strings set their response Content-Type to `text/plain`. By using the
25//! `RawHtml` content response, the Content-Type will be set to `text/html`
26//! instead:
27//!
28//! ```rust
29//! use rocket::response::content;
30//!
31//! let response = content::RawHtml("<h1>Hello, world!</h1>");
32//! ```
33
34use crate::request::Request;
35use crate::response::{self, Response, Responder};
36use crate::http::ContentType;
37
38macro_rules! ctrs {
39    ($($name:ident: $ct:ident, $name_str:expr, $ct_str:expr),+) => {
40        $(
41            #[doc="Override the `Content-Type` of the response to <b>"]
42            #[doc=$name_str]
43            #[doc="</b>, or <i>"]
44            #[doc=$ct_str]
45            #[doc="</i>."]
46            ///
47            /// Delegates the remainder of the response to the wrapped responder.
48            ///
49            /// **Note:** Unlike types like [`Json`](crate::serde::json::Json)
50            /// and [`MsgPack`](crate::serde::msgpack::MsgPack), this type _does
51            /// not_ serialize data in any way. You should _always_ use those
52            /// types to respond with serializable data. Additionally, you
53            /// should _always_ use [`NamedFile`](crate::fs::NamedFile), which
54            /// automatically sets a `Content-Type`, to respond with file data.
55            #[derive(Debug, Clone, PartialEq)]
56            pub struct $name<R>(pub R);
57
58            /// Sets the Content-Type of the response then delegates the
59            /// remainder of the response to the wrapped responder.
60            impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $name<R> {
61                fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
62                    (ContentType::$ct, self.0).respond_to(req)
63                }
64            }
65        )+
66    }
67}
68
69ctrs! {
70    // FIXME: Add a note that this is _not_ `serde::Json`.
71    RawJson: JSON, "JSON", "application/json",
72    RawXml: XML, "XML", "text/xml",
73    RawMsgPack: MsgPack, "MessagePack", "application/msgpack",
74    RawHtml: HTML, "HTML", "text/html",
75    RawText: Text, "plain text", "text/plain",
76    RawCss: CSS, "CSS", "text/css",
77    RawJavaScript: JavaScript, "JavaScript", "application/javascript"
78}
79
80impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (ContentType, R) {
81    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
82        Response::build()
83            .merge(self.1.respond_to(req)?)
84            .header(self.0)
85            .ok()
86    }
87}