Rocket - Blog using request guard - FromRequest



examples/rocket/blog-with-guard/src/main.rs
#[macro_use]
extern crate rocket;

#[cfg(test)]
mod tests;

use rocket::fs::relative;
use rocket::http::Status;
use rocket::outcome::Outcome;
use rocket::request::{self, FromRequest, Request};
use rocket::response::content;

struct MyGuard;

#[rocket::async_trait]
impl<'r> FromRequest<'r> for MyGuard {
    type Error = ();

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
        rocket::info!("from_request");
        rocket::info!("ip: {:?}", req.real_ip());
        let slug: std::path::PathBuf = req.segments(1..).unwrap();
        rocket::info!("path: {:?}", slug);
        let mut filepath = std::path::PathBuf::from(relative!("pages")).join(slug);
        filepath.set_extension("md");
        rocket::info!("filepath: {:?}", filepath);

        if filepath.exists() {
            Outcome::Success(MyGuard)
        } else {
            Outcome::Error((Status::NotFound, ()))
        }
    }
}

#[get("/")]
fn index() -> content::RawHtml<String> {
    let html = String::from(
        r#"
    <a href="/blog/main">main</a><br>
    <a href="/blog/missing">missing</a><br>
    "#,
    );
    content::RawHtml(html)
}

#[get("/blog/<slug>")]
fn blog(slug: &str, _g: MyGuard) -> content::RawHtml<String> {
    let mut filepath = std::path::PathBuf::from(relative!("pages")).join(slug);
    filepath.set_extension("md");
    let content = std::fs::read_to_string(filepath).unwrap();

    let html = format!("slug: {:?} content: {}", slug, content);

    content::RawHtml(html)
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index, blog])
}

examples/rocket/blog-with-guard/src/tests.rs
use rocket::http::Status;
use rocket::local::blocking::Client;

#[test]
fn check_index() {
    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(r#"<a href="/blog/main">main</a><br>"#));
    assert!(html.contains(r#"<a href="/blog/missing">missing</a><br>"#));
}

#[test]
fn check_main() {
    let client = Client::tracked(super::rocket()).unwrap();
    let response = client.get("/blog/main").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();
    //println!("{html}");
    assert!(html.contains(r#"slug: "main" content: Main page"#));
}

#[test]
fn check_about() {
    let client = Client::tracked(super::rocket()).unwrap();
    let response = client.get("/blog/about").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();
    //println!("{html}");
    assert!(html.contains(r#"slug: "about" content: About page"#));
}

#[test]
fn check_missing_page() {
    let client = Client::tracked(super::rocket()).unwrap();
    let response = client.get("/blog/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();
    println!("{html}");
    assert!(html.contains(r#"<title>404 Not Found</title>"#));
}

examples/rocket/blog-with-guard/pages/about.md
About page

examples/rocket/blog-with-guard/pages/main.md
Main page