Templating using askama

Askama implements a type-safe, Jinja-like template engine. While the templating engine itself is independent of any particular application, the askama_axum crate provides additional integration points by converting template results to response objects. Because Askama evaluates templates at compile time, it is both safe to use and fast to evaluate. On the other hand, it cannot be fed with templates by users at run-time.

Dependencies

[dependencies]
askama = { git = "https://github.com/djc/askama", features = ["with-axum"] }
askama_axum = { git = "https://github.com/djc/askama" }
axum = "0.5"
tokio = { version = "1", features = ["full"] }

Code

First create a new sibling directory templates next to the src directory and add an index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Askama</title>
  </head>

  <body>
    <p>Hello {{ name }}, you are {{ age }} years old.</p>
  </body>
</html>

Note that we refer to the two template variables name and age. Thanks to the compile-time guarantees of askama, the compiler will complain if we do not derive a template that contains these variables:

use askama::Template;
use axum::extract::Path;
use axum::routing::get;
use axum::Server;

#[derive(Template)]
#[template(path = "index.html")]
struct HtmlTemplate {
    name: String,
    age: u8,
}

async fn index(Path((name, age)): Path<(String, u8)>) -> HtmlTemplate {
    HtmlTemplate { name, age }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let app = axum::Router::new().route("/:name/:age", get(index));

    Server::bind(&"0.0.0.0:8080".parse()?)
        .serve(app.into_make_service())
        .await?;

    Ok(())
}

Run

Start the server with

cargo run --bin templating-with-askama

Now, lets try to get /john/32:

$ curl -i http://127.0.0.1:8080/john/32
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 167
date: Tue, 08 Mar 2022 20:13:10 GMT

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Askama</title>
  </head>

  <body>
    <p>Hello john, you are 32 years old.</p>
  </body>
</html>