Rocket is a brand-new web framework for Rust with one of the friendliest guides I’ve ever seen. Having basically no experience with either Rust or web development, I decided to give it a shot.
(Note: At the time of writing, Rocket requires Rust nightly.)
Say we have a function which generates passphrases. It takes arguments for how many words you want in the phrase, and how many digits should be tacked on.
fn passphrase_gen(num_words: u8, num_digits: u8) -> String {
...
}
With Rocket, we can define type-safe query strings by a simple struct of their elements. Let’s have optional parameters for our length and digit counts, with defaults we can use otherwise.
#[derive(FromForm)]
struct PhraseParams {
length: Option<u8>,
digits: Option<u8>
}
static DEFAULT_LENGTH: u8 = 4;
static DEFAULT_DIGITS: u8 = 0;
Rocket automatically performs validation. In this case, if one of our parameters is left off, or the value provided is not a u8
, we get a None
for that field. So, when something tries to access ourserver.com/passphrase?[whatever]
, let’s translate that to a passphrase_gen()
call with appropriate values.
#[get("/passphrase?<params>")]
fn phrase_params(params: PhraseParams) -> String {
let num_words = params.length.unwrap_or(DEFAULT_LENGTH);
let num_digits = params.digits.unwrap_or(DEFAULT_DIGITS);
passphrase_gen(num_words, num_digits)
}
You can have multiple routes going to the same path, and specify their order of priority using rank
. If someone tries going to /passphrase
without a query string, or with a nonsensical one, we can have a fallback.
#[get("/passphrase", rank = 2)]
fn phrase() -> String {
passphrase_gen(DEFAULT_LENGTH, DEFAULT_DIGITS)
}
This repository contains a working demo with a Handlebars HTML template that uses XML HTTP requests to our route to update an element’s contents. It also contains some lazy_static
insanity for a global CSPRNG and baked-in dictionary for the actual passphrase generator.
Shawn Kinkade — January, 2017