Implementations

Rocket implements Responder for many types in Rust’s standard library including String, &str, File, Option, and Result. The Responder documentation describes these in detail, but we briefly cover a few here.

Strings

The Responder implementations for &str and String are straight-forward: the string is used as a sized body, and the Content-Type of the response is set to text/plain. To get a taste for what such a Responder implementation looks like, here’s the implementation for String:

  1. impl Responder<'static> for String {
  2. fn respond_to(self, _: &Request) -> Result<Response<'static>, Status> {
  3. Response::build()
  4. .header(ContentType::Plain)
  5. .sized_body(Cursor::new(self))
  6. .ok()
  7. }
  8. }

Because of these implementations, you can directly return an &str or String type from a handler:

  1. #[get("/string")]
  2. fn handler() -> &'static str {
  3. "Hello there! I'm a string!"
  4. }

Option

Option is wrapping responder: an Option<T> can only be returned when T implements Responder. If the Option is Some, the wrapped responder is used to respond to the client. Otherwise, a error of 404 - Not Found is returned to the client.

This implementation makes Option a convenient type to return when it is not known until process-time whether content exists. For example, because of Option, we can implement a file server that returns a 200 when a file is found and a 404 when a file is not found in just 4, idiomatic lines:

  1. #[get("/<file..>")]
  2. fn files(file: PathBuf) -> Option<NamedFile> {
  3. NamedFile::open(Path::new("static/").join(file)).ok()
  4. }

Result

Result is a special kind of wrapping responder: its functionality depends on whether the error type E implements Responder.

When the error type E implements Responder, the wrapped Responder in Ok or Err, whichever it might be, is used to respond to the client. This means that the responder can be chosen dynamically at run-time, and two different kinds of responses can be used depending on the circumstances. Revisiting our file server, for instance, we might wish to provide more feedback to the user when a file isn’t found. We might do this as follows:

  1. use rocket::response::status::NotFound;
  2. #[get("/<file..>")]
  3. fn files(file: PathBuf) -> Result<NamedFile, NotFound<String>> {
  4. let path = Path::new("static/").join(file);
  5. NamedFile::open(&path).map_err(|_| NotFound(format!("Bad path: {}", path)))
  6. }

If the error type E does not implement Responder, then the error is simply logged to the console, using its Debug implementation, and a 500 error is returned to the client.