Rocket - In-memory counter using State
- A single counter in-memory counter (multiple browsers share the counter)
examples/rocket/in-memory-counter/Cargo.toml
[package] name = "in-memory-counter" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1", features = ["tera"] } serde = "1.0.201"
examples/rocket/in-memory-counter/src/main.rs
#[macro_use] extern crate rocket; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use serde::Deserialize; use rocket::{fairing::AdHoc, State}; use rocket_dyn_templates::{context, Template}; struct HitCount { count: AtomicUsize, } #[derive(Deserialize)] struct MyConfig { title: String, } #[get("/")] fn index(hit_count: &State<HitCount>, config: &State<MyConfig>) -> Template { //let current_count = hit_count.count.load(Ordering::Relaxed); let current_count = hit_count.count.fetch_add(1, Ordering::Relaxed); Template::render( "index", context! { title: &config.title, count: current_count, }, ) } #[catch(404)] fn not_found() -> Template { Template::render( "404", context! { // Currently the title is set in the template //title: "404 Not Found" }, ) } #[launch] fn rocket() -> _ { rocket::build() .mount("/", routes![index]) .attach(Template::fairing()) .attach(AdHoc::config::<MyConfig>()) .manage(HitCount { count: AtomicUsize::new(0), }) .register("/", catchers![not_found]) } #[cfg(test)] mod tests;
examples/rocket/in-memory-counter/src/tests.rs
use rocket::http::Status; use rocket::local::blocking::Client; #[test] fn hello_world() { let client = Client::tracked(super::rocket()).unwrap(); let response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!( response.headers().get_one("Content-Type").unwrap(), "text/html; charset=utf-8" ); let html = response.into_string().unwrap(); assert!(html.contains("<title>Rocket with Tera</title>")); assert!(html.contains("<h1>Rocket with Tera</h1>")); } #[test] fn page_not_found() { let client = Client::tracked(super::rocket()).unwrap(); let response = client.get("/other").dispatch(); assert_eq!(response.status(), Status::NotFound); assert_eq!( response.headers().get_one("Content-Type").unwrap(), "text/html; charset=utf-8" ); let html = response.into_string().unwrap(); //assert_eq!(html, ""); assert!(html.contains("<title>404 Not Found</title>")); assert!(html.contains("<h1>404 Not Found</h1>")); assert!(html.contains("<div>Page not found</div>")); }
examples/rocket/in-memory-counter/Rocket.toml
[default] title = "Rocket with Tera" [debug] [release]
examples/rocket/in-memory-counter/templates/404.html.tera
{% set title = "404 Not Found" %} {% include "incl/header" %} <div>Page not found</div> {% include "incl/footer" %}
examples/rocket/in-memory-counter/templates/incl/footer.html.tera
</body> </html>
examples/rocket/in-memory-counter/templates/incl/header.html.tera
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes"> <title>{{ title }}</title> </head> <body> <h1>{{title}}</h1>
examples/rocket/in-memory-counter/templates/index.html.tera
{% include "incl/header" %} <div> Welcome to your Rocket project! Counted: {{count}} </div> {% include "incl/footer" %}