rocket_dyn_templates/
fairing.rs
1use rocket::{Rocket, Build, Orbit};
2use rocket::fairing::{self, Fairing, Info, Kind};
3use rocket::figment::{Source, value::magic::RelativePathBuf};
4use rocket::trace::Trace;
5
6use crate::context::{Callback, Context, ContextManager};
7use crate::template::DEFAULT_TEMPLATE_DIR;
8use crate::engine::Engines;
9
10pub struct TemplateFairing {
15 pub callback: Callback,
19}
20
21#[rocket::async_trait]
22impl Fairing for TemplateFairing {
23 fn info(&self) -> Info {
24 let kind = Kind::Ignite | Kind::Liftoff;
25 #[cfg(debug_assertions)] let kind = kind | Kind::Request;
26
27 Info { kind, name: "Templating" }
28 }
29
30 async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
36 let configured_dir = rocket.figment()
37 .extract_inner::<RelativePathBuf>("template_dir")
38 .map(|path| path.relative());
39
40 let path = match configured_dir {
41 Ok(dir) => dir,
42 Err(e) if e.missing() => DEFAULT_TEMPLATE_DIR.into(),
43 Err(e) => {
44 e.trace_error();
45 return Err(rocket);
46 }
47 };
48
49 if let Some(ctxt) = Context::initialize(&path, &self.callback) {
50 Ok(rocket.manage(ContextManager::new(ctxt)))
51 } else {
52 error!("Template initialization failed. Aborting launch.");
53 Err(rocket)
54 }
55 }
56
57 async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {
58 let cm = rocket.state::<ContextManager>()
59 .expect("Template ContextManager registered in on_ignite");
60
61 span_info!("templating" => {
62 info!(directory = %Source::from(&*cm.context().root));
63 info!(engines = ?Engines::ENABLED_EXTENSIONS);
64 });
65 }
66
67 #[cfg(debug_assertions)]
68 async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &mut rocket::Data<'_>) {
69 let cm = req.rocket().state::<ContextManager>()
70 .expect("Template ContextManager registered in on_ignite");
71
72 cm.reload_if_needed(&self.callback);
73 }
74}