diff --git a/core/lib/src/fs/named_file.rs b/core/lib/src/fs/named_file.rs
index 29093582..8fd165f2 100644
--- a/core/lib/src/fs/named_file.rs
+++ b/core/lib/src/fs/named_file.rs
@@ -8,7 +8,8 @@ use crate::request::Request;
use crate::response::{self, Responder};
use crate::http::ContentType;
-/// A [`Responder`] that sends a file with a Content-Type based on its name.
+/// A [`Responder`] that sends file data with a Content-Type based on its
+/// file extension.
///
/// # Example
///
diff --git a/core/lib/src/response/content.rs b/core/lib/src/response/content.rs
index cb5006ac..68d7a33d 100644
--- a/core/lib/src/response/content.rs
+++ b/core/lib/src/response/content.rs
@@ -2,15 +2,11 @@
//!
//! # 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`.
+//! Each type in this module is a `Responder` that wraps an existing
+//! `Responder`, overwriting the `Content-Type` of the response but otherwise
+//! delegating the response to the wrapped responder. As a convenience,
+//! `(ContentType, R)` where `R: Responder` is _also_ a `Responder` that
+//! overrides the `Content-Type` to the value in `.0`:
//!
//! ```rust
//! # use rocket::get;
@@ -21,55 +17,24 @@
//! (ContentType::HTML, "Is this HTML?
Sure, why not!
")
//! }
//! ```
-
//!
//! # 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.
+//! The following snippet creates a `RawHtml` response from a string. Normally,
+//! raw strings set their response Content-Type to `text/plain`. By using the
+//! `RawHtml` content response, the Content-Type will be set to `text/html`
+//! instead:
//!
//! ```rust
//! use rocket::response::content;
//!
-//! # #[allow(unused_variables)]
-//! let response = content::Html("Hello, world!
");
+//! let response = content::RawHtml("Hello, world!
");
//! ```
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(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 {
- 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),+) => {
$(
@@ -80,6 +45,13 @@ macro_rules! ctrs {
#[doc="."]
///
/// Delegates the remainder of the response to the wrapped responder.
+ ///
+ /// **Note:** Unlike types like [`Json`](crate::serde::json::Json)
+ /// and [`MsgPack`](crate::serde::msgpack::MsgPack), this type _does
+ /// not_ serialize data in any way. You should _always_ use those
+ /// types to respond with serializable data. Additionally, you
+ /// should _always_ use [`NamedFile`](crate::fs::NamedFile), which
+ /// automatically sets a `Content-Type`, to respond with file data.
#[derive(Debug, Clone, PartialEq)]
pub struct $name(pub R);
@@ -87,7 +59,7 @@ macro_rules! ctrs {
/// remainder of the response to the wrapped responder.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $name {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
- Custom(ContentType::$ct, self.0).respond_to(req)
+ (ContentType::$ct, self.0).respond_to(req)
}
}
)+
@@ -96,18 +68,20 @@ macro_rules! ctrs {
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"
+ RawJson: JSON, "JSON", "application/json",
+ RawXml: XML, "XML", "text/xml",
+ RawMsgPack: MsgPack, "MessagePack", "application/msgpack",
+ RawHtml: HTML, "HTML", "text/html",
+ RawText: Text, "plain text", "text/plain",
+ RawCss: CSS, "CSS", "text/css",
+ RawJavaScript: 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)
+ fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
+ Response::build()
+ .merge(self.1.respond_to(req)?)
+ .header(self.0)
+ .ok()
}
}
diff --git a/core/lib/src/serde/json.rs b/core/lib/src/serde/json.rs
index 4827ea72..70ff50f0 100644
--- a/core/lib/src/serde/json.rs
+++ b/core/lib/src/serde/json.rs
@@ -223,7 +223,7 @@ impl<'r, T: Serialize> Responder<'r, 'static> for Json {
Status::InternalServerError
})?;
- content::Json(string).respond_to(req)
+ content::RawJson(string).respond_to(req)
}
}
@@ -299,7 +299,7 @@ impl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for Json {
/// and a fixed-size body with the serialized value.
impl<'r> Responder<'r, 'static> for Value {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
- content::Json(self.to_string()).respond_to(req)
+ content::RawJson(self.to_string()).respond_to(req)
}
}
diff --git a/core/lib/src/serde/msgpack.rs b/core/lib/src/serde/msgpack.rs
index 48d727bb..188041b9 100644
--- a/core/lib/src/serde/msgpack.rs
+++ b/core/lib/src/serde/msgpack.rs
@@ -194,7 +194,7 @@ impl<'r, T: Serialize> Responder<'r, 'static> for MsgPack {
Status::InternalServerError
})?;
- content::MsgPack(buf).respond_to(req)
+ content::RawMsgPack(buf).respond_to(req)
}
}
diff --git a/core/lib/tests/head_handling.rs b/core/lib/tests/head_handling.rs
index 4832d269..367d212a 100644
--- a/core/lib/tests/head_handling.rs
+++ b/core/lib/tests/head_handling.rs
@@ -1,6 +1,7 @@
#[macro_use] extern crate rocket;
-use rocket::{http::Status, response::content};
+use rocket::http::Status;
+use rocket::response::content::RawJson;
#[get("/empty")]
fn empty() -> Status {
@@ -13,8 +14,8 @@ fn index() -> &'static str {
}
#[head("/other")]
-fn other() -> content::Json<&'static str> {
- content::Json("{ 'hi': 'hello' }")
+fn other() -> RawJson<&'static str> {
+ RawJson("{ 'hi': 'hello' }")
}
mod head_handling_tests {
diff --git a/examples/cookies/src/main.rs b/examples/cookies/src/main.rs
index 3a287acb..b22c2b71 100644
--- a/examples/cookies/src/main.rs
+++ b/examples/cookies/src/main.rs
@@ -5,12 +5,12 @@
mod session;
mod message;
-use rocket::response::content::Html;
+use rocket::response::content::RawHtml;
use rocket_dyn_templates::Template;
#[get("/")]
-fn index() -> Html<&'static str> {
- Html(r#"Set a Message or Use Sessions."#)
+fn index() -> RawHtml<&'static str> {
+ RawHtml(r#"Set a Message or Use Sessions."#)
}
#[launch]
diff --git a/examples/error-handling/src/main.rs b/examples/error-handling/src/main.rs
index b31cfe38..ffa0a6b1 100644
--- a/examples/error-handling/src/main.rs
+++ b/examples/error-handling/src/main.rs
@@ -17,16 +17,16 @@ fn forced_error(code: u16) -> Status {
}
#[catch(404)]
-fn general_not_found() -> content::Html<&'static str> {
- content::Html(r#"
+fn general_not_found() -> content::RawHtml<&'static str> {
+ content::RawHtml(r#"
Hmm... What are you looking for?
Say hello!
"#)
}
#[catch(404)]
-fn hello_not_found(req: &Request<'_>) -> content::Html {
- content::Html(format!("\
+fn hello_not_found(req: &Request<'_>) -> content::RawHtml {
+ content::RawHtml(format!("\
Sorry, but '{}' is not a valid path!
\
Try visiting /hello/<name>/<age> instead.
",
req.uri()))
diff --git a/examples/pastebin/src/main.rs b/examples/pastebin/src/main.rs
index 0b990310..e88e0c07 100644
--- a/examples/pastebin/src/main.rs
+++ b/examples/pastebin/src/main.rs
@@ -7,7 +7,7 @@ use std::io;
use rocket::data::{Data, ToByteUnit};
use rocket::http::uri::Absolute;
-use rocket::response::content::Plain;
+use rocket::response::content::RawText;
use rocket::tokio::fs::{self, File};
use crate::paste_id::PasteId;
@@ -24,8 +24,8 @@ async fn upload(paste: Data<'_>) -> io::Result {
}
#[get("/")]
-async fn retrieve(id: PasteId<'_>) -> Option> {
- File::open(id.file_path()).await.map(Plain).ok()
+async fn retrieve(id: PasteId<'_>) -> Option> {
+ File::open(id.file_path()).await.map(RawText).ok()
}
#[delete("/")]
diff --git a/examples/responders/src/main.rs b/examples/responders/src/main.rs
index ca5328ac..e7ba7cea 100644
--- a/examples/responders/src/main.rs
+++ b/examples/responders/src/main.rs
@@ -89,26 +89,26 @@ fn maybe_redir(name: &str) -> Result<&'static str, Redirect> {
use rocket::Request;
use rocket::response::content;
-// NOTE: This example explicitly uses the `Json` type from `response::content`
-// for demonstration purposes. In a real application, _always_ prefer to use
-// `rocket::serde::json::Json` instead!
+// NOTE: This example explicitly uses the `RawJson` type from
+// `response::content` for demonstration purposes. In a real application,
+// _always_ prefer to use `rocket::serde::json::Json` instead!
// In a `GET` request and all other non-payload supporting request types, the
// preferred media type in the Accept header is matched against the `format` in
// the route attribute. Because the client can use non-specific media types like
// `*/*` in `Accept`, these first two routes would collide without `rank`.
#[get("/content", format = "xml", rank = 1)]
-fn xml() -> content::Xml<&'static str> {
- content::Xml("I'm here")
+fn xml() -> content::RawXml<&'static str> {
+ content::RawXml("I'm here")
}
#[get("/content", format = "json", rank = 2)]
-fn json() -> content::Json<&'static str> {
- content::Json(r#"{ "payload": "I'm here" }"#)
+fn json() -> content::RawJson<&'static str> {
+ content::RawJson(r#"{ "payload": "I'm here" }"#)
}
#[catch(404)]
-fn not_found(request: &Request<'_>) -> content::Html {
+fn not_found(request: &Request<'_>) -> content::RawHtml {
let html = match request.format() {
Some(ref mt) if !(mt.is_xml() || mt.is_html()) => {
format!("'{}' requests are not supported.
", mt)
@@ -118,24 +118,24 @@ fn not_found(request: &Request<'_>) -> content::Html {
request.uri())
};
- content::Html(html)
+ content::RawHtml(html)
}
/******************************* `Either` Responder ***************************/
use rocket::Either;
-use rocket::response::content::{Json, MsgPack};
+use rocket::response::content::{RawJson, RawMsgPack};
use rocket::http::uncased::AsUncased;
// NOTE: In a real application, we'd use `Json` and `MsgPack` from
// `rocket::serde`, which perform automatic serialization of responses and
// automatically set the `Content-Type`.
#[get("/content/")]
-fn json_or_msgpack(kind: &str) -> Either, MsgPack<&'static [u8]>> {
+fn json_or_msgpack(kind: &str) -> Either, RawMsgPack<&'static [u8]>> {
if kind.as_uncased() == "msgpack" {
- Either::Right(MsgPack(&[162, 104, 105]))
+ Either::Right(RawMsgPack(&[162, 104, 105]))
} else {
- Either::Left(Json("\"hi\""))
+ Either::Left(RawJson("\"hi\""))
}
}
@@ -143,7 +143,7 @@ fn json_or_msgpack(kind: &str) -> Either, MsgPack<&'static [u
use std::borrow::Cow;
-use rocket::response::content::Html;
+use rocket::response::content::RawHtml;
#[derive(Responder)]
enum StoredData {
@@ -151,7 +151,7 @@ enum StoredData {
String(Cow<'static, str>),
Bytes(Vec),
#[response(status = 401)]
- NotAuthorized(Html<&'static str>),
+ NotAuthorized(RawHtml<&'static str>),
}
#[derive(FromFormField, UriDisplayQuery)]
@@ -170,7 +170,7 @@ async fn custom(kind: Option) -> StoredData {
},
Some(Kind::String) => StoredData::String("Hey, I'm some data.".into()),
Some(Kind::Bytes) => StoredData::Bytes(vec![72, 105]),
- None => StoredData::NotAuthorized(Html("No no no!"))
+ None => StoredData::NotAuthorized(RawHtml("No no no!"))
}
}
diff --git a/examples/state/src/managed_hit_count.rs b/examples/state/src/managed_hit_count.rs
index 6138eead..1b02ce7b 100644
--- a/examples/state/src/managed_hit_count.rs
+++ b/examples/state/src/managed_hit_count.rs
@@ -1,15 +1,15 @@
use std::sync::atomic::{AtomicUsize, Ordering};
use rocket::State;
-use rocket::response::content;
+use rocket::response::content::RawHtml;
use rocket::fairing::AdHoc;
struct HitCount(AtomicUsize);
#[get("/")]
-fn index(hit_count: &State) -> content::Html {
+fn index(hit_count: &State) -> RawHtml {
let count = hit_count.0.fetch_add(1, Ordering::Relaxed) + 1;
- content::Html(format!("Your visit is recorded!
Visits: {}", count))
+ RawHtml(format!("Your visit is recorded!
Visits: {}", count))
}
pub fn stage() -> AdHoc {
diff --git a/examples/templating/src/main.rs b/examples/templating/src/main.rs
index 72dff9ac..e849f427 100644
--- a/examples/templating/src/main.rs
+++ b/examples/templating/src/main.rs
@@ -5,12 +5,12 @@ mod tera;
#[cfg(test)] mod tests;
-use rocket::response::content::Html;
+use rocket::response::content::RawHtml;
use rocket_dyn_templates::Template;
#[get("/")]
-fn index() -> Html<&'static str> {
- Html(r#"See Tera or Handlebars."#)
+fn index() -> RawHtml<&'static str> {
+ RawHtml(r#"See Tera or Handlebars."#)
}
#[launch]
diff --git a/site/guide/5-responses.md b/site/guide/5-responses.md
index 2ee90249..c1a744c4 100644
--- a/site/guide/5-responses.md
+++ b/site/guide/5-responses.md
@@ -50,7 +50,7 @@ fn new(id: usize) -> status::Accepted {
Similarly, the types in the [`content` module](@api/rocket/response/content/)
can be used to override the Content-Type of a response. For instance, to set the
Content-Type of `&'static str` to JSON, as well as setting the status code to an
-arbitrary one like `418 I'm a teapot`, combine [`content::Json`] with
+arbitrary one like `418 I'm a teapot`, combine [`content::RawJson`] with
[`status::Custom`]:
```rust
@@ -59,16 +59,16 @@ use rocket::http::Status;
use rocket::response::{content, status};
#[get("/")]
-fn json() -> status::Custom> {
- status::Custom(Status::ImATeapot, content::Json("{ \"hi\": \"world\" }"))
+fn json() -> status::Custom> {
+ status::Custom(Status::ImATeapot, content::RawJson("{ \"hi\": \"world\" }"))
}
```
! warning: This is _not_ the same as [`serde::json::Json`]!
The built-in `(Status, R)` and `(ContentType, R)` responders, where `R:
-Responder`, are short-hands for the `status::Custom` and `content::Custom`
-responders:
+Responder`, also override the `Status` and `Content-Type` of responses,
+respectively:
```rust
# #[macro_use] extern crate rocket;