#tera #actix-web #reduce-boilerplate #web

actix_tera_page

A middleware for Actix that reduces the boilerplate needed to create SSR websites with Tera

1 unstable release

0.1.0 Oct 12, 2023

#15 in #reduce-boilerplate

MIT license

16KB
119 lines

actix_tera_page

This crate provides a middleware for actix_web that reduces the boilerplate needed to create SSR websites with Tera. It matches GET request paths to templates and renders them using a shared "base context". An example use case would be populating a website navbar with user information or login/signup buttons, depending on if there is a user logged in or not.


lib.rs:

This crate provides a middleware for actix_web that reduces the boilerplate needed to create SSR websites with Tera. It matches GET request paths to templates and renders them using a shared "base context". An example use case would be populating a website navbar with user information or login/signup buttons, depending on if there is a user logged in or not.

To get started, create an async function that accepts HttpResponse, returning Context. Register a Tera object as app data on the web server, then wrap the application or route in the middleware constructed with TeraPage::new.

struct State {
    name: String,
}

async fn base_context(req: HttpRequest) -> Context {
   let state = req.app_data::<Data<State>>().unwrap();
   let mut context = Context::new();
   
   // This function could, for example, make SQL queries
   // through a connection stored in `State`.
   context.insert("username", &state.name);

   context
}

#[get("/complex-page")]
async fn complex_page(tera: web::Data<Tera>, req: HttpRequest) -> impl Responder {
    // The `base_context` function can be reused as a starting point
    // for pages with more complex requirements.
    let mut context = base_context(req.clone());
    context.insert("more-info", "data");
    tera.render("complex-page.html", &context).unwrap()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
   let state = web::Data::new(State {
       name: "User Name".to_string(),
   });

   let tera = web::Data::new(match Tera::new("templates/**/*.html") {
       Ok(t) => t,
       Err(e) => {
           println!("Parsing error(s): {}", e);
           ::std::process::exit(1);
       }
   });

   HttpServer::new(move || {
       App::new()
           .app_data(state.clone())
           .app_data(tera.clone())
           .service(complex_page)
           .wrap(TeraPage::new("pages", base_context))
   })
   .bind(("127.0.0.1", 8080))?
   .run()
   .await
}

A functional example can be found in the examples directory.

Dependencies

~21–32MB
~581K SLoC