From de6632ea56cce497d23a8f2223b8f8721202ff39 Mon Sep 17 00:00:00 2001 From: Azan Ali <73800719+aznszn@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:33:56 +0500 Subject: [PATCH] Improve wrapping responders guide section. --- docs/guide/06-responses.md | 60 ++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/docs/guide/06-responses.md b/docs/guide/06-responses.md index 31a10d323c..1b9fcd29c7 100644 --- a/docs/guide/06-responses.md +++ b/docs/guide/06-responses.md @@ -25,18 +25,20 @@ responses according to the incoming `Request` they are responding to. ### Wrapping -Before we describe a few responders, we note that it is typical for responders -to _wrap_ other responders. That is, responders can be of the following form, -where `R` is some type that implements `Responder`: +Responders compose by _wrapping_ (encapsulating) other responders. Naturally, we +call these _wrapping_ responders. A wrapping responder takes a response from an +existing responder `R`, modifies it, and then returns it. They typically have +the following shape: ```rust struct WrappingResponder(R); ``` -A wrapping responder modifies the response returned by `R` before responding -with that same response. For instance, Rocket provides `Responder`s in the -[`status` module](@api/master/rocket/response/status/) that override the status code of -the wrapped `Responder`. As an example, the [`Accepted`] type sets the status to +Examples include `Responder`s in the [`status` module], which override the +status code of the wrapped `Responder`'s response, and `Responder`s in the +[`content` module], which override the Content-Type. + +As a concrete example, the [`Accepted`] wrapping responder sets the status to `202 - Accepted`. It can be used as follows: ```rust @@ -47,15 +49,17 @@ use rocket::response::status; #[post("/")] fn new(id: usize) -> status::Accepted { + // Modifies the response generated by `String` to have a status of `202`. status::Accepted(format!("id: '{}'", id)) } ``` -Similarly, the types in the [`content` module](@api/master/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::RawJson`] with -[`status::Custom`]: +Because wrapping responders are themselves responders, they too can be wrapped. +This is what allows responders to compose, enabling powerful combinations of +simple primitives to form more powerful abstractions. For example, combining the +[`content::RawJson`] and [`status::Custom`] responders allows creating a +response with a Content-Type of JSON and an arbitrary status code like `418 I'm +a teapot` from an `&'static str`: ```rust # #[macro_use] extern crate rocket; @@ -70,21 +74,25 @@ fn json() -> status::Custom> { ! warning: This is _not_ the same as [`serde::json::Json`]! -The built-in `(Status, R)` and `(ContentType, R)` responders, where `R: -Responder`, also override the `Status` and `Content-Type` of responses, -respectively: +! note: There are simpler alternatives for setting a status and content-types. -```rust -# #[macro_use] extern crate rocket; -use rocket::http::{Status, ContentType}; + The built-in `(Status, R)` and `(ContentType, R)` wrapping responders + also override the `Status` and `Content-Type` of responses, respectively, and + may be simpler alternatives: -#[get("/")] -fn json() -> (Status, (ContentType, &'static str)) { - (Status::ImATeapot, (ContentType::JSON, "{ \"hi\": \"world\" }")) -} -``` + ```rust + # #[macro_use] extern crate rocket; + use rocket::http::{Status, ContentType}; + + #[get("/")] + fn json() -> (Status, (ContentType, &'static str)) { + (Status::ImATeapot, (ContentType::JSON, "{ \"hi\": \"world\" }")) + } + ``` -For pithy reusability, it is advisable to derive a [custom responder]: +Composition through wrapping is useful when you want to change one or two +properties of an existing response. For more complex use-cases, instead consider +deriving a [custom responder]: ```rust # #[macro_use] extern crate rocket; @@ -100,10 +108,12 @@ fn json() -> RawTeapotJson { ``` [`Accepted`]: @api/master/rocket/response/status/struct.Accepted.html -[`content::Json`]: @api/master/rocket/response/content/struct.Json.html +[`content::RawJson`]: @api/master/rocket/response/content/struct.RawJson.html [`status::Custom`]: @api/master/rocket/response/status/struct.Custom.html [`serde::json::Json`]: @api/master/rocket/serde/json/struct.Json.html [custom responder]: #custom-responders +[`status` module]: @api/master/rocket/response/status/ +[`content` module]: @api/master/rocket/response/content/ ### Errors