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

reduce minijinja boilerplate

This commit is contained in:
Rob Ede 2022-10-16 21:36:23 +01:00
parent 8a22559cac
commit bf0386ade7
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
5 changed files with 62 additions and 35 deletions

1
Cargo.lock generated
View File

@ -6242,6 +6242,7 @@ dependencies = [
name = "templating-minijinja"
version = "1.0.0"
dependencies = [
"actix-utils",
"actix-web",
"actix-web-lab 0.18.5",
"env_logger 0.9.1",

View File

@ -32,7 +32,7 @@ async fn main() -> std::io::Result<()> {
"/",
web::to(|data: web::Data<usize>| async move {
assert_eq!(**data, 123);
HttpResponse::NoContent()
HttpResponse::NoContent().finish()
}),
)
})

View File

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
actix-web = "4"
actix-web-lab = "0.18"
actix-utils = "3"
env_logger = "0.9"
log = "0.4"

View File

@ -1,39 +1,66 @@
use actix_utils::future::{ready, Ready};
use std::collections::HashMap;
use actix_web::{
dev::ServiceResponse,
dev::{self, ServiceResponse},
error,
http::{header::ContentType, StatusCode},
middleware::{ErrorHandlerResponse, ErrorHandlers, Logger},
web, App, Error, HttpResponse, HttpServer, Responder, Result,
web, App, FromRequest, HttpRequest, HttpResponse, HttpServer, Responder, Result,
};
use actix_web_lab::respond::Html;
async fn index(
#[derive(Debug)]
struct MiniJinjaRenderer {
tmpl_env: web::Data<minijinja::Environment<'static>>,
query: web::Query<HashMap<String, String>>,
) -> Result<impl Responder, Error> {
let html = if let Some(name) = query.get("name") {
let tmpl = tmpl_env
.get_template("user.html")
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
}
let ctx = minijinja::context! {
impl MiniJinjaRenderer {
fn render(
&self,
tmpl: &str,
ctx: impl Into<minijinja::value::Value>,
) -> actix_web::Result<Html> {
self.tmpl_env
.get_template(tmpl)
.map_err(|_| error::ErrorInternalServerError("could not find template"))?
.render(ctx.into())
.map(Html)
.map_err(|err| {
log::error!("{err}");
error::ErrorInternalServerError("template error")
})
}
}
impl FromRequest for MiniJinjaRenderer {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
let tmpl_env = <web::Data<minijinja::Environment<'static>>>::from_request(req, payload)
.into_inner()
.unwrap();
ready(Ok(Self { tmpl_env }))
}
}
async fn index(
tmpl_env: MiniJinjaRenderer,
query: web::Query<HashMap<String, String>>,
) -> actix_web::Result<impl Responder> {
if let Some(name) = query.get("name") {
tmpl_env.render(
"user.html",
minijinja::context! {
name,
text => "Welcome!",
};
tmpl.render(ctx)
.map_err(|_| error::ErrorInternalServerError("Template error"))?
},
)
} else {
tmpl_env
.get_template("index.html")
.map_err(|_| error::ErrorInternalServerError("Template error"))?
.render(())
.map_err(|_| error::ErrorInternalServerError("Template error"))?
};
Ok(Html(html))
tmpl_env.render("index.html", ())
}
}
#[actix_web::main]
@ -75,6 +102,8 @@ fn not_found<B>(svc_res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>
fn get_error_response<B>(res: &ServiceResponse<B>, error: &str) -> HttpResponse {
let req = res.request();
let tmpl_env = MiniJinjaRenderer::extract(req).into_inner().unwrap();
// Provide a fallback to a simple plain text response in case an error occurs during the
// rendering of the error page.
let fallback = |err: &str| {
@ -88,17 +117,13 @@ fn get_error_response<B>(res: &ServiceResponse<B>, error: &str) -> HttpResponse
status_code => res.status().as_str(),
};
match req
.app_data::<web::Data<minijinja::Environment>>()
.and_then(|tmpl_env| tmpl_env.get_template("error.html").ok())
.and_then(|tmpl| tmpl.render(ctx).ok())
{
Some(body) => Html(body)
match tmpl_env.render("error.html", ctx) {
Ok(body) => body
.customize()
.with_status(res.status())
.respond_to(&req)
.respond_to(req)
.map_into_boxed_body(),
None => fallback(error),
Err(_) => fallback(error),
}
}

View File

@ -6,7 +6,7 @@ use actix_web::{
error,
http::{header::ContentType, StatusCode},
middleware::{self, ErrorHandlerResponse, ErrorHandlers},
web, App, Error, HttpResponse, HttpServer, Result,
web, App, Error, HttpResponse, HttpServer, Responder, Result,
};
use actix_web_lab::respond::Html;
use tera::Tera;
@ -15,7 +15,7 @@ use tera::Tera;
async fn index(
tmpl: web::Data<tera::Tera>,
query: web::Query<HashMap<String, String>>,
) -> Result<HttpResponse, Error> {
) -> Result<impl Responder, Error> {
let s = if let Some(name) = query.get("name") {
// submitted form
let mut ctx = tera::Context::new();