This is a demonstration of:
-
The Rust programming language
-
The Rocket 0.5 web framework
This demo is a quick start of the most-important areas for the projects we build. This demo is not intended to be a production-ready application, and is not intended to cover all Rocket capabilities. For that, see the Rocket documentation.
Feedback welcome.
Setup:
- Rocket.toml configuration file
- Environment variable file .env.example
- Git ignore file .gitignore
- Install sccache (Shared Compilation Cache)
- Install diesel_cli (Diesel Command Line Interface)
Demos as source code:
- static_route.rs: Static route "/hello"
- dynamic_route.rs: Dynamic route "/echo"
- method_routes.rs: Method routes for HTTP GET, PUT, POST, PATCH, HEAD, OPTIONS
- form.rs: Form demo
- upload.rs: Upload demo
Capabilities:
- Cookies and CookieJar
- Databases using SQLite, sqlx, and a connection pool
- JSON request and response.
- Static file
- Static files with path segments
- Static files with a file server
- Templates with Tera templating engine
Follow this guide:
Create an app:
cargo new demo-rust-rocket --bin
cd demo-rust-rocket
Edit file Cargo.toml
to add dependency:
[dependencies]
rocket = "0.5.0"
Edit file main.rs
to be:
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
Run:
cargo test
You should see minimal output because so far there are no tests:
Finished test [unoptimized + debuginfo] target(s) in 0.18s
Running unittests src/main.rs (target/debug/deps/demo_rust_rocket-54a4eaafb5adb876)
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Run:
cargo run
You should see:
Running `target/debug/demo-rust-rocket`
π§ Configured for debug.
>> address: 127.0.0.1
>> port: 8000
>> workers: 10
>> max blocking threads: 512
>> ident: Rocket
>> IP header: X-Real-IP
>> limits: bytes = 8KiB, data-form = 2MiB, file = 1MiB, form = 32KiB, json = 1MiB, msgpack = 1MiB, string = 8KiB
>> temp dir: /var/folders/77/xrhg507j46x_bwpzhtbmn3pw0000gn/T/
>> http/2: true
>> keep-alive: 5s
>> tls: disabled
>> shutdown: ctrlc = true, force = true, signals = [SIGTERM], grace = 2s, mercy = 3s
>> log level: normal
>> cli colors: true
π¬ Routes:
>> (index) GET /
π‘ Fairings:
>> Shield (liftoff, response, singleton)
π‘οΈ Shield:
>> X-Frame-Options: SAMEORIGIN
>> Permissions-Policy: interest-cohort=()
>> X-Content-Type-Options: nosniff
π Rocket has launched from http://127.0.0.1:8000
Browse:
You should see:
Hello, world!
To launch a Rocket application, the suggested approach is to return an instance of Rocket<Build>
from a function named rocket marked with the #[launch]
attribute.
This generates a main function with an async runtime that runs the returned Rocket instance.
Example:
#[launch]
fn rocket() -> _ {
rocket::build()
}
We refactor because we prefer a more-flexible more-explicit approach.
We separate the Rocket "build phase" from the later "ignite phase" and "launch phase". This will enable us to test more easily because we can create Rocket instances for testing.
use rocket::{Build, Rocket};
fn rocket() -> Rocket<Build> {
rocket::build().mount("/", routes![index])
}
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
let _rocket = rocket()
.ignite().await?
.launch().await?;
Ok(())
}
Create a demos module directory:
mkdir src/demos
Create a demos module file src/demos/mod.rs
:
pub mod index;
Create a file src/demos/index.rs
:
// Demo of an index route handler, a unit test, and client test.
// When a browser client does a typical HTTP GET request to "/"
// then this handler responds with the text "Hello, world!".
#[get("/")]
pub fn handler() -> &'static str {
"Hello, world!"
}
#[cfg(test)]
mod tests {
use crate::rocket;
use rocket::local::blocking::Client;
use rocket::http::{ContentType, Status};
#[test]
fn unit() {
assert_eq!(super::handler(), "Hello, world!");
}
#[test]
fn client() {
let client = Client::tracked(rocket()).expect("rocket");
let response = client.get("/").dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::Plain));
assert_eq!(response.into_string(), Some("Hello, world!".into()));
}
}
Run:
cargo test
You should see the tests passed:
running 2 tests
test demos::index::tests::unit ... ok
test demos::index::tests::system ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Run:
cargo run
Browse:
You should see:
Hello, world!
Rocket features include:
http2
: Support for HTTP/2 (enabled by default).json
: Support for JSON (de)serialization.msgpack
: Support for MessagePack (de)serialization.uuid
: Support for UUID value parsing and (de)serialization.secrets
: Support for authenticated, encrypted private cookies.tls
: Support for TLS encrypted connections.mtls
: Support for verified clients via mutual TLS.
Options:
-
For templating support, depend on
rocket_dyn_templates
. Features include templating with Handlebars and/or Tera . -
For database pools, depend on
rocket_sync_db_pools
and/orrocket_db_pools
. -
For JSON support, depend on
serde
.
Edit file Cargo.toml
to add your preferred dependencies, such as:
[dependencies]
rocket = { version = "0.5.0", features = ["http2", "json", "msgpack", "uuid", "secrets", "tls", "mtls"] }
rocket_dyn_templates = { version = "0.1.0", features = ["handlebars", "tera"] }
rocket_db_pools = { version = "0.1.0", features = ["sqlx_sqlite"] }
serde = { version = "1.0", features = ["derive"] }