Rocket Responders

Some of Rocket’s best features are implemented through responders. You can find many of these responders in the response module. Among these are:

  • Content - Used to override the Content-Type of a response.
  • NamedFile - Streams a file to the client; automatically sets the Content-Type based on the file’s extension.
  • Redirect - Redirects the client to a different URI.
  • Stream - Streams a response to a client from an arbitrary Reader type.
  • status - Contains types that override the status code of a response.
  • Flash - Sets a “flash” cookie that is removed when accessed.

Streaming

The Stream type deserves special attention. When a large amount of data needs to be sent to the client, it is better to stream the data to the client to avoid consuming large amounts of memory. Rocket provides the Stream type, making this easy. The Stream type can be created from any Read type. For example, to stream from a local Unix stream, we might write:

  1. #[get("/stream")]
  2. fn stream() -> io::Result<Stream<UnixStream>> {
  3. UnixStream::connect("/path/to/my/socket").map(|s| Stream::from(s))
  4. }

JSON

The JSON responder in rocket_contrib allows you to easily respond with well-formed JSON data: simply return a value of type Json<T> where T is the type of a structure to serialize into JSON. The type T must implement the Serialize trait from serde, which can be automatically derived.

As an example, to respond with the JSON value of a Task structure, we might write:

  1. use rocket_contrib::Json;
  2. #[derive(Serialize)]
  3. struct Task { ... }
  4. #[get("/todo")]
  5. fn todo() -> Json<Task> { ... }

The JSON type serializes the structure into JSON, sets the Content-Type to JSON, and emits the serialized data in a fixed-sized body. If serialization fails, a 500 - Internal Server Error is returned.

The JSON example on GitHub provides further illustration.

Templates

Rocket includes built-in templating support that works largely through a Template responder in rocket_contrib. To render a template named “index”, for instance, you might return a value of type Template as follows:

  1. #[get("/")]
  2. fn index() -> Template {
  3. let context = /* object-like value */;
  4. Template::render("index", &context)
  5. }

Templates are rendered with the render method. The method takes in the name of a template and a context to render the template with. The context can be any type that implements Serialize and serializes into an Object value, such as structs, HashMaps, and others.

Rocket searches for a template with the given name in the configurable template_dir directory. Templating support in Rocket is engine agnostic. The engine used to render a template depends on the template file’s extension. For example, if a file ends with .hbs, Handlebars is used, while if a file ends with .tera, Tera is used.

For templates to be properly registered, the template fairing must be attached to the instance of Rocket. The Fairings sections of the guide provides more information on fairings. To attach the template fairing, simply call .attach(Template::fairing()) on an instance of Rocket as follows:

  1. fn main() {
  2. rocket::ignite()
  3. .mount("/", routes![...])
  4. .attach(Template::fairing());
  5. }

The Template API documentation contains more information about templates, while the Handlebars Templates example on GitHub is a fully composed application that makes use of Handlebars templates.