pub trait Responder<'r, 'o: 'r> {
// Required method
fn respond_to(self, request: &'r Request<'_>) -> Result<'o>;
}Expand description
Trait implemented by types that generate responses for clients.
Any type that implements Responder can be used as the return type of a
handler:
// This works for any `T` that implements `Responder`.
#[get("/")]
fn index() -> T { /* ... */ }§Deriving
This trait can, and largely should, be automatically derived. The derive
can handle all simple cases and most complex cases, too. When deriving
Responder, the first field of the annotated structure (or of each variant
if an enum) is used to generate a response while the remaining fields are
used as response headers:
use rocket::http::ContentType;
use rocket::serde::{Serialize, json::Json};
#[derive(Responder)]
enum Error<T> {
#[response(status = 400)]
Unauthorized(Json<T>),
#[response(status = 404)]
NotFound(Template, ContentType),
}For full details on deriving Responder, see the Responder derive.
§Provided Implementations
Rocket implements Responder for several standard library types. Their
behavior is documented here. Note that the Result implementation is
overloaded, allowing for two Responders to be used at once, depending on
the variant.
-
&str
Sets the
Content-Typetotext/plain. The string is used as the body of the response, which is fixed size and not streamed. To stream a raw string, useStream::from(Cursor::new(string)). -
String
Sets the
Content-Typetotext/plain. The string is used as the body of the response, which is fixed size and not streamed. To stream a string, useStream::from(Cursor::new(string)). -
&[u8]
Sets the
Content-Typetoapplication/octet-stream. The slice is used as the body of the response, which is fixed size and not streamed. To stream a slice of bytes, useStream::from(Cursor::new(data)). -
Vec<u8>
Sets the
Content-Typetoapplication/octet-stream. The vector’s data is used as the body of the response, which is fixed size and not streamed. To stream a vector of bytes, useStream::from(Cursor::new(vec)). -
File
Responds with a streamed body containing the data in the
File. NoContent-Typeis set. To automatically have aContent-Typeset based on the file’s extension, useNamedFile. -
()
Responds with an empty body. No
Content-Typeis set. -
Option<T>
If the
OptionisSome, the wrapped responder is used to respond to the client. Otherwise, anErrwith status 404 Not Found is returned and a warning is printed to the console. -
Result<T, E>
If the
ResultisOk, the wrappedOkresponder is used to respond to the client. If theResultisErr, the wrappedErrresponder is used to respond to the client.
§Return Value
A Responder returns a Result<Response, Status>.
-
An
Ok(Response)indicates success. TheResponsewill be written out to the client. -
An
Err(Status)indicates an error. The error catcher forStatuswill be invoked to generate a response.
§Implementation Tips
This section describes a few best practices to take into account when
implementing Responder.
-
Avoid Manual Implementations
The
Responderderive is a powerful mechanism that eliminates the need to implementResponderin almost all cases. We encourage you to explore using the derive before attempting to implementResponderdirectly. It allows you to leverage existingResponderimplementations through composition, decreasing the opportunity for mistakes or performance degradation. -
Joining and Merging
When chaining/wrapping other
Responders, start withResponse::build_from()and/or use themerge()orjoin()methods on theResponseorResponseBuilderstruct. Ensure that you document merging or joining behavior appropriately. -
Inspecting Requests
While tempting, a
Responderthat varies its functionality based on the incoming request sacrifices its functionality being understood based purely on its type. By implication, gleaning the functionality of a handler from its type signature also becomes more difficult. You should avoid varying responses based on theRequestvalue as much as possible. -
Perform
asyncI/O in ConstructorsThe
Respondertrait is not anasynctrait. This is not an oversight. Instead of performingasyncoperations in what would be therespond_tomethod, perform them in a constructor for the responder. As an example, seeNamedFile::open(), which performs the requisite I/O forNamedFile’s responder.
§Lifetimes
Responder has two lifetimes: Responder<'r, 'o: 'r>.
-
'rbounds the reference to the&'r Request. -
'obounds the returnedResponse<'o>to values that live at least as long as the request.This includes borrows from the
Requestitself (where'owould be'ras inimpl<'r> Responder<'r, 'r>) as well as'staticdata (where'owould be'staticas inimpl<'r> Responder<'r, 'static>).
In practice, you are likely choosing between four signatures:
// If the response contains no borrowed data.
impl<'r> Responder<'r, 'static> for A {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
todo!()
}
}
// If the response borrows from the request.
impl<'r> Responder<'r, 'r> for B<'r> {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {
todo!()
}
}
// If the response is or wraps a borrow that may outlive the request.
impl<'r, 'o: 'r> Responder<'r, 'o> for &'o C {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
todo!()
}
}
// If the response wraps an existing responder.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for D<R> {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
todo!()
}
}§Example
Say that you have a custom type, Person:
struct Person {
name: String,
age: u16
}You’d like to use Person as a Responder so that you can return a
Person directly from a handler:
#[get("/person/<id>")]
fn person(id: usize) -> Option<Person> {
Person::from_id(id)
}You want the Person responder to set two header fields: X-Person-Name
and X-Person-Age as well as supply a custom representation of the object
(Content-Type: application/x-person) in the body of the response. The
following Responder implementation accomplishes this:
use std::io::Cursor;
use rocket::request::Request;
use rocket::response::{self, Response, Responder};
use rocket::http::ContentType;
impl<'r> Responder<'r, 'static> for Person {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
let string = format!("{}:{}", self.name, self.age);
Response::build_from(string.respond_to(req)?)
.raw_header("X-Person-Name", self.name)
.raw_header("X-Person-Age", self.age.to_string())
.header(ContentType::new("application", "x-person"))
.ok()
}
}Note that the implementation could have instead been derived if structured in a slightly different manner:
use rocket::http::Header;
use rocket::response::Responder;
#[derive(Responder)]
#[response(content_type = "application/x-person")]
struct Person {
text: String,
name: Header<'static>,
age: Header<'static>,
}
impl Person {
fn new(name: &str, age: usize) -> Person {
Person {
text: format!("{}:{}", name, age),
name: Header::new("X-Person-Name", name.to_string()),
age: Header::new("X-Person-Age", age.to_string())
}
}
}Required Methods§
Sourcefn respond_to(self, request: &'r Request<'_>) -> Result<'o>
fn respond_to(self, request: &'r Request<'_>) -> Result<'o>
Returns Ok if a Response could be generated successfully. Otherwise,
returns an Err with a failing Status.
The request parameter is the Request that this Responder is
responding to.
When using Rocket’s code generation, if an Ok(Response) is returned,
the response will be written out to the client. If an Err(Status) is
returned, the error catcher for the given status is retrieved and called
to generate a final error response, which is then written out to the
client.
Implementations on Foreign Types§
Source§impl<'r> Responder<'r, 'static> for ()
Returns an empty, default Response. Always returns Ok.
impl<'r> Responder<'r, 'static> for ()
Returns an empty, default Response. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'static>
Source§impl<'r> Responder<'r, 'static> for Arc<str>
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
impl<'r> Responder<'r, 'static> for Arc<str>
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'static>
Source§impl<'r> Responder<'r, 'static> for Arc<[u8]>
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
impl<'r> Responder<'r, 'static> for Arc<[u8]>
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'static>
Source§impl<'r> Responder<'r, 'static> for File
Returns a response with a sized body for the file. Always returns Ok.
impl<'r> Responder<'r, 'static> for File
Returns a response with a sized body for the file. Always returns Ok.
fn respond_to(self, req: &'r Request<'_>) -> Result<'static>
Source§impl<'r> Responder<'r, 'static> for Error
Prints a warning with the error and forwards to the 500 error catcher.
impl<'r> Responder<'r, 'static> for Error
Prints a warning with the error and forwards to the 500 error catcher.
fn respond_to(self, _: &'r Request<'_>) -> Result<'static>
Source§impl<'r> Responder<'r, 'static> for File
Returns a response with a sized body for the file. Always returns Ok.
impl<'r> Responder<'r, 'static> for File
Returns a response with a sized body for the file. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'static>
Source§impl<'r, 'o: 'r> Responder<'r, 'o> for &'o str
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
impl<'r, 'o: 'r> Responder<'r, 'o> for &'o str
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'o>
Source§impl<'r, 'o: 'r> Responder<'r, 'o> for &'o [u8]
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
impl<'r, 'o: 'r> Responder<'r, 'o> for &'o [u8]
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
fn respond_to(self, _: &'r Request<'_>) -> Result<'o>
Source§impl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for Either<T, E>
Responds with the wrapped Responder in self, whether it is Left or
Right.
impl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for Either<T, E>
Responds with the wrapped Responder in self, whether it is Left or
Right.
fn respond_to(self, req: &'r Request<'_>) -> Result<'o>
Source§impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (ContentType, R)
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (ContentType, R)
fn respond_to(self, req: &'r Request<'_>) -> Result<'o>
Source§impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (Status, R)
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (Status, R)
fn respond_to(self, request: &'r Request<'_>) -> Result<'o>
Source§impl<'r, 'o: 'r, R: ?Sized + ToOwned> Responder<'r, 'o> for Cow<'o, R>
Responds with the inner Responder in Cow.
impl<'r, 'o: 'r, R: ?Sized + ToOwned> Responder<'r, 'o> for Cow<'o, R>
Responds with the inner Responder in Cow.
fn respond_to(self, req: &'r Request<'_>) -> Result<'o>
Implementors§
impl<'r> Responder<'r, 'static> for Value
json only.Serializes the value into JSON. Returns a response with Content-Type JSON and a fixed-size body with the serialized value.
impl<'r> Responder<'r, 'static> for NamedFile
Streams the named file to the client. Sets or overrides the Content-Type in
the response according to the file’s extension if the extension is
recognized. See ContentType::from_extension() for more information. If
you would like to stream a file with a different Content-Type than that
implied by its extension, use a File directly.
impl<'r> Responder<'r, 'static> for Status
The response generated by Status depends on the status code itself. The
table below summarizes the functionality:
| Status Code Range | Response |
|---|---|
| [400, 599] | Forwards to catcher for given status. |
| 100, [200, 205] | Empty with status of self. |
| All others. | Invalid. Errors to 500 catcher. |
In short, a client or server error status codes will forward to the
corresponding error catcher, a successful status code less than 206 or
100 responds with any empty body and the given status code, and all other
status code emit an error message and forward to the 500 (internal server
error) catcher.
impl<'r> Responder<'r, 'static> for Box<str>
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
impl<'r> Responder<'r, 'static> for Box<[u8]>
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
impl<'r> Responder<'r, 'static> for String
Returns a response with Content-Type text/plain and a fixed-size body
containing the string self. Always returns Ok.
impl<'r> Responder<'r, 'static> for Vec<u8>
Returns a response with Content-Type application/octet-stream and a
fixed-size body containing the data in self. Always returns Ok.
impl<'r> Responder<'r, 'static> for NoContent
Sets the status code of the response to 204 No Content.
impl<'r> Responder<'r, 'static> for Redirect
Constructs a response with the appropriate status code and the given URL in
the Location header field. The body of the response is empty. If the URI
value used to create the Responder is an invalid URI, an error of
Status::InternalServerError is returned.
impl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for Result<T, E>
Responds with the wrapped Responder in self, whether it is Ok or
Err.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Option<R>
If self is Some, responds with the wrapped Responder. Otherwise prints
a warning message and returns an Err of Status::NotFound.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for RawCss<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 RawHtml<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 RawJavaScript<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 RawJson<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 RawMsgPack<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 RawText<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 RawXml<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 Accepted<R>
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for BadRequest<R>
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Conflict<R>
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Created<R>
Sets the status code of the response to 201 Created. Sets the Location
header to the parameter in the Created::new() constructor.
The optional responder, set via Created::body() or
Created::tagged_body() finalizes the response if it exists. The wrapped
responder should write the body of the response so that it contains
information about the created resource. If no responder is provided, the
response body will be empty.
In addition to setting the status code, Location header, and finalizing
the response with the Responder, the ETag header is set conditionally if
a hashable Responder is provided via Created::tagged_body(). The ETag
header is set to a hash value of the responder.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Custom<R>
Sets the status code of the response and then delegates the remainder of the response to the wrapped responder.
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Forbidden<R>
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for NotFound<R>
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Flash<R>
Sets the message cookie and then uses the wrapped responder to complete the
response. In other words, simply sets a cookie and delegates the rest of the
response handling to the wrapped responder. As a result, the Outcome of
the response is the Outcome of the wrapped Responder.
impl<'r, 'o: 'r, T: Responder<'r, 'o> + Sized> Responder<'r, 'o> for Box<T>
Returns the response generated by the inner T. Note that this explicitly
does not support Box<dyn Responder>.
#[macro_use] extern crate rocket;
use rocket::response::Responder;
#[get("/")]
fn f() -> Box<dyn Responder<'static,'static>> {
Box::new(())
}However, this impl allows boxing sized responders:
#[macro_use] extern crate rocket;
#[derive(Responder)]
enum Content {
Redirect(Box<rocket::response::Redirect>),
Text(String),
}
#[get("/")]
fn f() -> Option<Box<String>> {
None
}
#[get("/")]
fn g() -> Content {
Content::Text("hello".to_string())
}impl<'r, 'o: 'r, T: Responder<'r, 'o>> Responder<'r, 'o> for Capped<T>
impl<'r, E: Debug> Responder<'r, 'static> for Debug<E>
impl<'r, S> Responder<'r, 'r> for ByteStream<S>
impl<'r, S> Responder<'r, 'r> for ReaderStream<S>
impl<'r, S> Responder<'r, 'r> for TextStream<S>
impl<'r, S: Stream<Item = Event> + Send + 'r> Responder<'r, 'r> for EventStream<S>
impl<'r, T: Serialize> Responder<'r, 'static> for Json<T>
json only.Serializes the wrapped value into JSON. Returns a response with Content-Type
JSON and a fixed-size body with the serialized value. If serialization
fails, an Err of Status::InternalServerError is returned.
impl<'r, T: Serialize> Responder<'r, 'static> for MsgPack<T>
msgpack only.Serializes the wrapped value into MessagePack. Returns a response with
Content-Type MsgPack and a fixed-size body with the serialization. If
serialization fails, an Err of Status::InternalServerError is returned.