# Rocket v0.2: Managed State & More

Posted by Sergio Benitez on February 06, 2017

Today marks the first major release since Rocket's debut a little over a month ago. Rocket v0.2 packs a ton of new features, fixes, and general improvements. Much of the development in v0.2 was led by the community, either through reports via the [GitHub issue tracker](https://github.com/rwf2/Rocket/issues) or via direct contributions. In fact, there have been **20 unique contributors** to Rocket's codebase since Rocket's initial introduction! Community feedback has been incredible. As a special thank you, we include the names of these contributors at the end of this article. ## About Rocket Rocket is a web framework for Rust with a focus on ease of use, expressiveness, and speed. Rocket makes it simple to write fast web applications without sacrificing flexibility or type safety. All with minimal code. > Rocket's so simple, you feel like you're doing something wrong. It's like if > you're making fire with rocks and suddenly someone gives you a lighter. Even > though you know the lighter makes fire, and does it even faster and better and > with a simple flick, the rock's still in your brain. > > -- Artem "impowski" Biryukov, January 17, 2017, on **#rocket** ## New Features Rocket v0.2 includes several new features that make developing Rocket applications simpler, faster, and safer than ever before. ### Managed State Undoubtedly, the star feature of this release is **managed state**. Managed state allows you to pass state to Rocket prior to launching your application and later retrieve that state from any request handler by simply including the state's type in the function signature. It works in two easy steps: 1. Call `manage` on the `Rocket` instance corresponding to your application with the initial value of the state. 2. Add a `State` type to any request handler, where `T` is the type of the value passed into `manage`. Rocket takes care of the rest! `State` works through Rocket's [request guards](@guide-v0.3/requests/#request-guards). You can call `manage` any number of times, as long as each call corresponds to a value of a different type. As a simple example, consider the following "hit counter" example application: ```rust struct HitCount(AtomicUsize); #[get("/")] fn index(hit_count: State) -> &'static str { hit_count.0.fetch_add(1, Ordering::Relaxed); "Your visit has been recorded!" } #[get("/count")] fn count(hit_count: State) -> String { hit_count.0.load(Ordering::Relaxed).to_string() } fn main() { rocket::ignite() .mount("/", routes![index, count]) .manage(HitCount(AtomicUsize::new(0))) .launch() } ``` Visiting `/` will record a visit by incrementing the hit count by 1. Visiting the `/count` path will display the current hit count. One concern when using _managed state_ is that you might forget to call `manage` with some state's value before launching your application. Not to worry: Rocket has your back! Let's imagine for a second that we forgot to add the call to `manage` on line 17 in the example above. Here's what the compiler would emit when we compile our buggy application: ```rust warning: HitCount is not currently being managed by Rocket --> src/main.rs:4:21 | 4 | fn index(hit_count: State) -> &'static str { | ^^^^^^^^^^^^^^^ | = note: this State request guard will always fail help: maybe add a call to 'manage' here? --> src/main.rs:15:5 | 15| rocket::ignite() | ^^^^^^^^^^^^^^^^ warning: HitCount is not currently being managed by Rocket --> src/main.rs:10:21 | 10 | fn count(hit_count: State) -> String { | ^^^^^^^^^^^^^^^ | = note: this State request guard will always fail help: maybe add a call to 'manage' here? --> src/main.rs:15:5 | 15 | rocket::ignite() | ^^^^^^^^^^^^^^^^ ``` You can read more about managed state in the [guide](@guide-v0.3/state/), the API docs for [manage](@api-v0.3/rocket/struct.Rocket.html#method.manage), and the API docs for [State](@api-v0.3/rocket/struct.State.html). ### Unmounted Routes Lint A common mistake that new Rocketeers make is forgetting to [mount](@guide-v0.3/overview/#mounting) declared routes. In Rocket v0.2, Rocket adds a _lint_ that results in a compile-time warning for unmounted routes. As a simple illustration, consider the canonical "Hello, world!" Rocket application below, and note that we've forgotten to mount the `hello` route: ```rust #[get("/")] fn hello() -> &'static str { "Hello, world!" } fn main() { rocket::ignite().launch(); } ``` When this program is compiled, the compiler emits the following warning: ```rust warning: the 'hello' route is not mounted --> src/main.rs:2:1 | 2 | fn hello() -> &'static str { | _^ starting here... 3 | | "Hello, world!" 4 | | } | |_^ ...ending here | = note: Rocket will not dispatch requests to unmounted routes. help: maybe add a call to 'mount' here? --> src/main.rs:7:5 | 7 | rocket::ignite().launch(); | ^^^^^^^^^^^^^^^^ ``` The lint can be disabled selectively per route by adding an `#[allow(unmounted_route)]` annotation to a given route declaration. It can also be disabled globally by adding `#![allow(unmounted_route)]`. You can read more about this lint in the [codegen documentation](@api-v0.3/rocket_codegen/index.html). ### Configuration via Environment Variables A new feature that makes deploying Rocket apps to the cloud a little easier is configuration via environment variables. Simply put, any configuration parameter can be set via an environment variable of the form `ROCKET_{PARAM}`, where `{PARAM}` is the name of the configuration parameter. For example, to set the `port` Rocket listens on, simply set the `ROCKET_PORT` environment variable: ```sh ROCKET_PORT=3000 cargo run --release ``` Configuration parameters set via environment variables take precedence over parameters set via the `Rocket.toml` configuration file. Note that _any_ parameter can be set via an environment variable, include _extras_. For more about configuration in Rocket, see the [configuration section of the guide](@guide-v0.3/configuration). ### And Plenty More! Rocket v0.2 is full of many new features! In addition to the three features described above, v0.2 also includes the following: * `Config` structures can be built via `ConfigBuilder`, which follows the builder pattern. * Logging can be enabled or disabled on custom configuration via a second parameter to the `Rocket::custom` method. * `name` and `value` methods were added to `Header` to retrieve the name and value of a header. * A new configuration parameter, `workers`, can be used to set the number of threads Rocket uses. * The address of the remote connection is available via `Request.remote()`. Request preprocessing overrides remote IP with value from the `X-Real-IP` header, if present. * During testing, the remote address can be set via `MockRequest.remote()`. * The `SocketAddr` request guard retrieves the remote address. * A `UUID` type has been added to `contrib`. * `rocket` and `rocket_codegen` will refuse to build with an incompatible nightly version and emit nice error messages. * Major performance and usability improvements were upstreamed to the `cookie` crate, including the addition of a `CookieBuilder`. * When a checkbox isn't present in a form, `bool` types in a `FromForm` structure will parse as `false`. * The `FormItems` iterator can be queried for a complete parse via `completed` and `exhausted`. * Routes for `OPTIONS` requests can be declared via the `options` decorator. * Strings can be percent-encoded via `URI::percent_encode()`. ## Breaking Changes This release includes several breaking changes. These changes are listed below along with a short note about how to handle the breaking change in existing applications. * **`Rocket::custom` takes two parameters, the first being `Config` by value.** A call in v0.1 of the form `Rocket::custom(&config)` is now `Rocket::custom(config, false)`. * **Tera templates are named without their extension.** A templated named `name.html.tera` is now simply `name`. * **`JSON` `unwrap` method has been renamed to `into_inner`.** A call to `.unwrap()` should be changed to `.into_inner()`. * **The `map!` macro was removed in favor of the `json!` macro.** A call of the form `map!{ "a" => b }` can be written as: `json!({ "a": b })`. * **The `hyper::SetCookie` header is no longer exported.** Use the `Cookie` type as an `Into
` type directly. * **The `Content-Type` for `String` is now `text/plain`.** Use `content::HTML` for HTML-based `String` responses. * **`Request.content_type()` returns an `Option`.** Use `.unwrap_or(ContentType::Any)` to get the old behavior. * **The `ContentType` request guard forwards when the request has no `Content-Type` header.** Use an `Option` and `.unwrap_or(ContentType::Any)` for the old behavior. * **A `Rocket` instance must be declared _before_ a `MockRequest`.** Change the order of the `rocket::ignite()` and `MockRequest::new()` calls. * **A route with `format` specified only matches requests with the same format.** Previously, a route with a `format` would match requests without a format specified. There is no workaround to this change; simply specify formats when required. * **`FormItems` can no longer be constructed directly.** Instead of constructing as `FormItems(string)`, construct as `FormItems::from(string)`. * **`from_from_string(&str)` in `FromForm` removed in favor of `from_form_items(&mut FormItems)`.** Most implementation should be using `FormItems` internally; simply use the passed in `FormItems`. In other cases, the form string can be retrieved via the `inner_str` method of `FormItems`. * **`Config::{set, default_for}` are deprecated.** Use the `set_{param}` methods instead of `set`, and `new` or `build` in place of `default_for`. * **Route paths must be absolute.** Prepend a `/` to convert a relative path into an absolute one. * **Route paths cannot contain empty segments.** Remove any empty segments, including trailing ones, from a route path. ## Bug Fixes Three bugs were fixed in this release: * Handlebars partials were not properly registered ([#122](https://github.com/rwf2/Rocket/issues/122)). * `Rocket::custom` did not set the custom configuration as the `active` configuration. * Route path segments with more than one dynamic parameter were erroneously allowed. ## General Improvements In addition to new features, Rocket saw the following smaller improvements: * Rocket no longer overwrites a catcher's response status. * The `port` `Config` type is now a proper `u16`. * Clippy issues injected by codegen are resolved. * Handlebars was updated to `0.25`. * The `PartialEq` implementation of `Config` doesn't consider the path or session key. * Hyper dependency updated to `0.10`. * The `Error` type for `JSON as FromData` has been exposed as `SerdeError`. * SVG was added as a known Content-Type. * Serde was updated to `0.9`. * Form parse failure now results in a **422** error code. * Tera has been updated to `0.7`. * `pub(crate)` is used throughout to enforce visibility rules. * Query parameters in routes (`/path?`) are now logged. * Routes with and without query parameters no longer _collide_. Rocket v0.2 also includes all of the new features, bug fixes, and improvements from versions 0.1.1 through 0.1.6. You can read more about these changes in the [v0.1 CHANGELOG](https://github.com/rwf2/Rocket/blob/v0.1/CHANGELOG.md). ## What's next? Work now begins on Rocket v0.3! The focus of the next major release will be on security. In particular, three major security features are planned: 1. **Automatic CSRF protection across all payload-based requests ([#14](https://github.com/rwf2/Rocket/issues/14)).** Rocket will automatically check the origin of requests made for HTTP `PUT`, `POST`, `DELETE`, and `PATCH` requests, allowing only authorized requests to be dispatched. This includes checking `POST`s from form submissions and any requests made via JavaScript. 2. **Encryption and signing of session-based cookies ([#20](https://github.com/rwf2/Rocket/issues/20)).** Built-in session support will encrypt and sign cookies using a user supplied `session_key`. Encryption and signing will occur automatically for session-based cookies. 3. **Explicit typing of raw HTTP data strings ([#43](https://github.com/rwf2/Rocket/issues/43)).** A present, the standard `&str` type is used to represent raw HTTP data strings. In the next release, a new type, `&RawStr`, will be used for this purpose. This will make it clear when raw data is being handled. The type will expose convenient methods such as `.url_decode()` and `.html_escape()`. Work on Rocket v0.3 will also involve exploring built-in support for user authentication and authorization as well as automatic parsing of multipart forms. ## Contributors to v0.2 The following wonderful people helped make Rocket v0.2 happen:
  • Cliff H
  • Dru Sellers
  • Eijebong
  • Eric D. Reichert
  • Ernestas Poskus
  • FliegendeWurst
  • Garrett Squire
  • Giovanni Capuano
  • Greg Edwards
  • Joel Roller
  • Josh Holmer
  • Liigo Zhuang
  • Lori Holden
  • Marcus Ball
  • Matt McCoy
  • Reilly Tucker Siemens
  • Robert Balicki
  • Sean Griffin
  • Seth Lopez
  • tborsa
Thank you all! Your contributions are greatly appreciated! Looking to help with Rocket's development? Head over to [Rocket's GitHub](https://github.com/rwf2/Rocket#contributing) and start contributing! ## Start using Rocket today! Not already using Rocket? Rocket is extensively documented, making it easy for you to start writing your web applications in Rocket! See the [overview](../../overview) or start writing code immediately by reading through [the guide](@guide-v0.3).