Improve wrapping responders guide section.

This commit is contained in:
Azan Ali 2024-08-24 16:33:56 +05:00 committed by Sergio Benitez
parent 72c91958b7
commit de6632ea56
1 changed files with 35 additions and 25 deletions

View File

@ -25,18 +25,20 @@ responses according to the incoming `Request` they are responding to.
### Wrapping ### Wrapping
Before we describe a few responders, we note that it is typical for responders Responders compose by _wrapping_ (encapsulating) other responders. Naturally, we
to _wrap_ other responders. That is, responders can be of the following form, call these _wrapping_ responders. A wrapping responder takes a response from an
where `R` is some type that implements `Responder`: existing responder `R`, modifies it, and then returns it. They typically have
the following shape:
```rust ```rust
struct WrappingResponder<R>(R); struct WrappingResponder<R>(R);
``` ```
A wrapping responder modifies the response returned by `R` before responding Examples include `Responder`s in the [`status` module], which override the
with that same response. For instance, Rocket provides `Responder`s in the status code of the wrapped `Responder`'s response, and `Responder`s in the
[`status` module](@api/master/rocket/response/status/) that override the status code of [`content` module], which override the Content-Type.
the wrapped `Responder`. As an example, the [`Accepted`] type sets the status to
As a concrete example, the [`Accepted`] wrapping responder sets the status to
`202 - Accepted`. It can be used as follows: `202 - Accepted`. It can be used as follows:
```rust ```rust
@ -47,15 +49,17 @@ use rocket::response::status;
#[post("/<id>")] #[post("/<id>")]
fn new(id: usize) -> status::Accepted<String> { fn new(id: usize) -> status::Accepted<String> {
// Modifies the response generated by `String` to have a status of `202`.
status::Accepted(format!("id: '{}'", id)) status::Accepted(format!("id: '{}'", id))
} }
``` ```
Similarly, the types in the [`content` module](@api/master/rocket/response/content/) Because wrapping responders are themselves responders, they too can be wrapped.
can be used to override the Content-Type of a response. For instance, to set the This is what allows responders to compose, enabling powerful combinations of
Content-Type of `&'static str` to JSON, as well as setting the status code to an simple primitives to form more powerful abstractions. For example, combining the
arbitrary one like `418 I'm a teapot`, combine [`content::RawJson`] with [`content::RawJson`] and [`status::Custom`] responders allows creating a
[`status::Custom`]: response with a Content-Type of JSON and an arbitrary status code like `418 I'm
a teapot` from an `&'static str`:
```rust ```rust
# #[macro_use] extern crate rocket; # #[macro_use] extern crate rocket;
@ -70,21 +74,25 @@ fn json() -> status::Custom<content::RawJson<&'static str>> {
! warning: This is _not_ the same as [`serde::json::Json`]! ! warning: This is _not_ the same as [`serde::json::Json`]!
The built-in `(Status, R)` and `(ContentType, R)` responders, where `R: ! note: There are simpler alternatives for setting a status and content-types.
Responder`, also override the `Status` and `Content-Type` of responses,
respectively:
```rust The built-in `(Status, R)` and `(ContentType, R)` wrapping responders
# #[macro_use] extern crate rocket; also override the `Status` and `Content-Type` of responses, respectively, and
use rocket::http::{Status, ContentType}; may be simpler alternatives:
#[get("/")] ```rust
fn json() -> (Status, (ContentType, &'static str)) { # #[macro_use] extern crate rocket;
(Status::ImATeapot, (ContentType::JSON, "{ \"hi\": \"world\" }")) use rocket::http::{Status, ContentType};
}
```
For pithy reusability, it is advisable to derive a [custom responder]: #[get("/")]
fn json() -> (Status, (ContentType, &'static str)) {
(Status::ImATeapot, (ContentType::JSON, "{ \"hi\": \"world\" }"))
}
```
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 ```rust
# #[macro_use] extern crate rocket; # #[macro_use] extern crate rocket;
@ -100,10 +108,12 @@ fn json() -> RawTeapotJson {
``` ```
[`Accepted`]: @api/master/rocket/response/status/struct.Accepted.html [`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 [`status::Custom`]: @api/master/rocket/response/status/struct.Custom.html
[`serde::json::Json`]: @api/master/rocket/serde/json/struct.Json.html [`serde::json::Json`]: @api/master/rocket/serde/json/struct.Json.html
[custom responder]: #custom-responders [custom responder]: #custom-responders
[`status` module]: @api/master/rocket/response/status/
[`content` module]: @api/master/rocket/response/content/
### Errors ### Errors