1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
//! Contains types that set the Content-Type of a response. //! //! # Usage //! //! Each type wraps a given responder. The `Responder` implementation of each //! type replaces the Content-Type of the wrapped responder and delegates the //! remainder of the response to the wrapped responder. This allows for setting //! the Content-Type of a type that doesn't set it itself or for overriding one //! that does. //! //! The [`Custom`] type allows responding with _any_ `Content-Type`. As a //! convenience, `(ContentType, R)` where `R: Responder` is _also_ a //! `Responder`, identical to `Custom`. //! //! ```rust //! # use rocket::get; //! use rocket::http::ContentType; //! //! #[get("/")] //! fn index() -> (ContentType, &'static str) { //! (ContentType::HTML, "Is this HTML? <p>Sure, why not!</p>") //! } //! ``` //! //! # Example //! //! The following snippet creates an `Html` content response for a string. //! Normally, raw strings set their response Content-Type to `text/plain`. By //! using the `Html` content response, the Content-Type will be set to //! `text/html` instead. //! //! ```rust //! use rocket::response::content; //! //! # #[allow(unused_variables)] //! let response = content::Html("<h1>Hello, world!</h1>"); //! ``` use crate::request::Request; use crate::response::{self, Response, Responder}; use crate::http::ContentType; /// Sets the Content-Type of a `Responder` to a chosen value. /// /// Delegates the remainder of the response to the wrapped responder. /// /// # Example /// /// Set the Content-Type of a string to PDF. /// /// ```rust /// use rocket::response::content::Custom; /// use rocket::http::ContentType; /// /// # #[allow(unused_variables)] /// let response = Custom(ContentType::PDF, "Hi."); /// ``` #[derive(Debug, Clone, PartialEq)] pub struct Custom<R>(pub ContentType, pub R); /// Overrides the Content-Type of the response to the wrapped `ContentType` then /// delegates the remainder of the response to the wrapped responder. impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Custom<R> { fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { Response::build() .merge(self.1.respond_to(req)?) .header(self.0) .ok() } } macro_rules! ctrs { ($($name:ident: $ct:ident, $name_str:expr, $ct_str:expr),+) => { $( #[doc="Override the `Content-Type` of the response to <b>"] #[doc=$name_str] #[doc="</b>, or <i>"] #[doc=$ct_str] #[doc="</i>."] /// /// Delegates the remainder of the response to the wrapped responder. #[derive(Debug, Clone, PartialEq)] pub struct $name<R>(pub R); /// Sets the Content-Type of the response then delegates the /// remainder of the response to the wrapped responder. impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $name<R> { fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { Custom(ContentType::$ct, self.0).respond_to(req) } } )+ } } ctrs! { // FIXME: Add a note that this is _not_ `serde::Json`. Json: JSON, "JSON", "application/json", Xml: XML, "XML", "text/xml", MsgPack: MsgPack, "MessagePack", "application/msgpack", Html: HTML, "HTML", "text/html", Plain: Plain, "plain text", "text/plain", Css: CSS, "CSS", "text/css", JavaScript: JavaScript, "JavaScript", "application/javascript" } impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (ContentType, R) { #[inline(always)] fn respond_to(self, request: &'r Request<'_>) -> response::Result<'o> { Custom(self.0, self.1).respond_to(request) } }