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