1
0
mirror of https://github.com/actix/examples synced 2024-11-23 22:41:07 +01:00

add auto reloading to minijinja

This commit is contained in:
Rob Ede 2022-10-16 21:49:01 +01:00
parent bf0386ade7
commit ae25a7908d
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
4 changed files with 116 additions and 13 deletions

77
Cargo.lock generated
View File

@ -2741,6 +2741,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
@ -3390,6 +3399,26 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "inout" name = "inout"
version = "0.1.3" version = "0.1.3"
@ -3667,6 +3696,26 @@ dependencies = [
"winapi-build", "winapi-build",
] ]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags",
"libc",
]
[[package]] [[package]]
name = "language-tags" name = "language-tags"
version = "0.3.2" version = "0.3.2"
@ -3951,6 +4000,16 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "minijinja-autoreload"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4caaefe206f2225f4da38d7f08aa7e1702920acc5505f01a7f33396766ae60a"
dependencies = [
"minijinja",
"notify",
]
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@ -4262,6 +4321,23 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "notify"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
dependencies = [
"bitflags",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio 0.8.4",
"walkdir",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.3.3" version = "0.3.3"
@ -6248,6 +6324,7 @@ dependencies = [
"env_logger 0.9.1", "env_logger 0.9.1",
"log", "log",
"minijinja", "minijinja",
"minijinja-autoreload",
] ]
[[package]] [[package]]

View File

@ -11,3 +11,4 @@ actix-utils = "3"
env_logger = "0.9" env_logger = "0.9"
log = "0.4" log = "0.4"
minijinja = { version = "0.23", features = ["source"] } minijinja = { version = "0.23", features = ["source"] }
minijinja-autoreload = "0.23"

View File

@ -6,7 +6,7 @@ Minimal example of using the template engine [MiniJinja](https://github.com/Keat
```sh ```sh
cd templating/minijinja cd templating/minijinja
cargo run TEMPLATE_AUTORELOAD=true cargo run
``` ```
- <http://localhost:8080> - <http://localhost:8080>

View File

@ -1,5 +1,6 @@
use actix_utils::future::{ready, Ready}; use actix_utils::future::{ready, Ready};
use std::collections::HashMap; use minijinja_autoreload::AutoReloader;
use std::{collections::HashMap, env, path::PathBuf};
use actix_web::{ use actix_web::{
dev::{self, ServiceResponse}, dev::{self, ServiceResponse},
@ -10,9 +11,8 @@ use actix_web::{
}; };
use actix_web_lab::respond::Html; use actix_web_lab::respond::Html;
#[derive(Debug)]
struct MiniJinjaRenderer { struct MiniJinjaRenderer {
tmpl_env: web::Data<minijinja::Environment<'static>>, tmpl_env: web::Data<minijinja_autoreload::AutoReloader>,
} }
impl MiniJinjaRenderer { impl MiniJinjaRenderer {
@ -22,6 +22,8 @@ impl MiniJinjaRenderer {
ctx: impl Into<minijinja::value::Value>, ctx: impl Into<minijinja::value::Value>,
) -> actix_web::Result<Html> { ) -> actix_web::Result<Html> {
self.tmpl_env self.tmpl_env
.acquire_env()
.map_err(|_| error::ErrorInternalServerError("could not acquire template env"))?
.get_template(tmpl) .get_template(tmpl)
.map_err(|_| error::ErrorInternalServerError("could not find template"))? .map_err(|_| error::ErrorInternalServerError("could not find template"))?
.render(ctx.into()) .render(ctx.into())
@ -37,8 +39,8 @@ impl FromRequest for MiniJinjaRenderer {
type Error = actix_web::Error; type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>; type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { fn from_request(req: &HttpRequest, _pl: &mut dev::Payload) -> Self::Future {
let tmpl_env = <web::Data<minijinja::Environment<'static>>>::from_request(req, payload) let tmpl_env = <web::Data<minijinja_autoreload::AutoReloader>>::extract(req)
.into_inner() .into_inner()
.unwrap(); .unwrap();
@ -67,17 +69,40 @@ async fn index(
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
log::info!("starting HTTP server at http://localhost:8080"); // If TEMPLATE_AUTORELOAD is set, then the path tracking is enabled.
let enable_template_autoreload = env::var("TEMPLATE_AUTORELOAD").as_deref() == Ok("true");
if enable_template_autoreload {
log::info!("template auto-reloading is enabled");
} else {
log::info!(
"template auto-reloading is disabled; run with TEMPLATE_AUTORELOAD=true to enable"
);
}
// The closure is invoked every time the environment is outdated to recreate it.
let tmpl_reloader = AutoReloader::new(move |notifier| {
let mut env: minijinja::Environment<'static> = minijinja::Environment::new(); let mut env: minijinja::Environment<'static> = minijinja::Environment::new();
env.set_source(minijinja::Source::from_path(concat!(
env!("CARGO_MANIFEST_DIR"), let tmpl_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("templates");
"/templates"
))); // if watch_path is never called, no fs watcher is created
if enable_template_autoreload {
notifier.watch_path(&tmpl_path, true);
}
env.set_source(minijinja::Source::from_path(tmpl_path));
Ok(env)
});
let tmpl_reloader = web::Data::new(tmpl_reloader);
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(move || { HttpServer::new(move || {
App::new() App::new()
.app_data(web::Data::new(env.clone())) .app_data(tmpl_reloader.clone())
.service(web::resource("/").route(web::get().to(index))) .service(web::resource("/").route(web::get().to(index)))
.wrap(ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)) .wrap(ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found))
.wrap(Logger::default()) .wrap(Logger::default())