use rocket::fs::FileServer; use rocket::fs::NamedFile; use rocket::http::ContentType; use rocket::http::Header; use crate::mushroom; use crate::render; use crate::translate; pub async fn run_server() { rocket::build() .mount("/", routes![index, healthz, generate]) .mount("/static", FileServer::from("static")) .launch() .await .unwrap(); } #[get("/")] async fn index() -> Option { NamedFile::open("static/index.html").await.ok() } #[get("/healthz")] fn healthz() -> &'static str { "ok" } // TODO: Wrap this with memoization via https://docs.rs/michie/latest/michie/ /// Do work to generate a binary STL for a given mushroom. fn generate_binary_stl(mushroom: mushroom::Mushroom) -> Vec { // Generate the binary STL in a byte array. let layers = translate::mushroom(&mushroom, 0.1); let mesh = render::render(&layers, 0.1); // Generate / return the byte array. let mut binary_stl = Vec::::new(); stl_io::write_stl(&mut binary_stl, mesh.iter()).unwrap(); return binary_stl; } /// Responder class for BinarySTL or Error. #[derive(Responder)] enum AsyncBinaryStlResponder { #[response(status = 500)] Error(&'static str), BinaryStl { inner: Vec, header: ContentType, filename: Header<'static>, }, } /// Take a mushroom struct, and generate a Responder with error handling, and header info. async fn generate_helper(mushroom: mushroom::Mushroom) -> AsyncBinaryStlResponder { let result = rocket::tokio::task::spawn_blocking(move || { // Return the byte array. return generate_binary_stl(mushroom); }) .await; return if result.is_ok() { AsyncBinaryStlResponder::BinaryStl { inner: result.unwrap(), header: ContentType::parse_flexible("model/x.stl-binary").unwrap(), filename: Header { name: "Content-Disposition".into(), value: "inline; filename=\"mushroom.stl\"".into(), }, } } else { AsyncBinaryStlResponder::Error("Internal JoinError") }; } /// Handler for /generate GEt endpoint. #[get("/generate?&&&&")] async fn generate( stalk_h: Option, stalk_r: Option, cap_h: Option, cap_r: Option, cap_style: Option, ) -> AsyncBinaryStlResponder { let mushroom = mushroom::Mushroom { stalk_h: stalk_h.unwrap_or(66.0), stalk_r: stalk_r.unwrap_or(5.0), cap_h: cap_h.unwrap_or(34.0), cap_r: cap_r.unwrap_or(50.0), cap_style: cap_style.unwrap_or(mushroom::CapStyle::Dome), }; return generate_helper(mushroom).await; }