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
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>(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("/<id>")]
fn new(id: usize) -> status::Accepted<String> {
// 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<content::RawJson<&'static str>> {
! 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)) {
```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