@@ -19,7 +19,8 @@ use iron::{
1919} ;
2020use serde:: Serialize ;
2121use std:: { borrow:: Cow , sync:: Arc } ;
22- use tera:: { Context , Tera } ;
22+ use tera:: Context ;
23+ use tokio:: task:: spawn_blocking;
2324
2425/// When making using a custom status, use a closure that coerces to a `fn(&Self) -> Status`
2526#[ macro_export]
@@ -61,11 +62,28 @@ macro_rules! impl_webpage {
6162
6263#[ macro_export]
6364macro_rules! impl_axum_webpage {
64- ( $page: ty = $template: literal $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
65- $crate:: impl_axum_webpage!( $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template) $( , status = $status) ? $( , content_type = $content_type) ?) ;
65+ (
66+ $page: ty = $template: literal
67+ $( , status = $status: expr) ?
68+ $( , content_type = $content_type: expr) ?
69+ $( , cpu_intensive_rendering = $cpu_intensive_rendering: expr) ?
70+ $( , ) ?
71+ ) => {
72+ $crate:: impl_axum_webpage!(
73+ $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template)
74+ $( , status = $status) ?
75+ $( , content_type = $content_type) ?
76+ $( , cpu_intensive_rendering = $cpu_intensive_rendering ) ?
77+ ) ;
6678 } ;
6779
68- ( $page: ty = $template: expr $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
80+ (
81+ $page: ty = $template: expr
82+ $( , status = $status: expr) ?
83+ $( , content_type = $content_type: expr) ?
84+ $( , cpu_intensive_rendering = $cpu_intensive_rendering: expr) ?
85+ $( , ) ?
86+ ) => {
6987 impl axum:: response:: IntoResponse for $page
7088 {
7189 fn into_response( self ) -> :: axum:: response:: Response {
@@ -76,6 +94,12 @@ macro_rules! impl_axum_webpage {
7694 ct = $content_type;
7795 ) ?
7896
97+ #[ allow( unused_mut, unused_assignments) ]
98+ let mut cpu_intensive_rendering = false ;
99+ $(
100+ cpu_intensive_rendering = $cpu_intensive_rendering;
101+ ) ?
102+
79103 let mut response = :: axum:: http:: Response :: builder( )
80104 . header( :: axum:: http:: header:: CONTENT_TYPE , ct)
81105 $(
@@ -96,6 +120,7 @@ macro_rules! impl_axum_webpage {
96120 let template: fn ( & Self ) -> :: std:: borrow:: Cow <' static , str > = $template;
97121 template( & self ) . to_string( )
98122 } ,
123+ cpu_intensive_rendering,
99124 } ) ;
100125 response
101126 }
@@ -189,14 +214,20 @@ pub trait WebPage: Serialize + Sized {
189214pub ( crate ) struct DelayedTemplateRender {
190215 pub template : String ,
191216 pub context : Context ,
217+ pub cpu_intensive_rendering : bool ,
192218}
193219
194- fn render_response ( mut response : AxumResponse , templates : & Tera , csp_nonce : & str ) -> AxumResponse {
220+ fn render_response (
221+ mut response : AxumResponse ,
222+ templates : Arc < TemplateData > ,
223+ csp_nonce : String ,
224+ ) -> AxumResponse {
195225 if let Some ( render) = response. extensions ( ) . get :: < DelayedTemplateRender > ( ) {
226+ let tera = & templates. templates ;
196227 let mut context = render. context . clone ( ) ;
197228 context. insert ( "csp_nonce" , & csp_nonce) ;
198229
199- let rendered = match templates . render ( & render. template , & context) {
230+ let rendered = match tera . render ( & render. template , & context) {
200231 Ok ( content) => content,
201232 Err ( err) => {
202233 if response. status ( ) . is_server_error ( ) {
@@ -239,5 +270,19 @@ pub(crate) async fn render_templates_middleware<B>(
239270 . nonce ( )
240271 . to_owned ( ) ;
241272
242- render_response ( next. run ( req) . await , & templates. templates , & csp_nonce)
273+ let response = next. run ( req) . await ;
274+
275+ let cpu_intensive_rendering: bool = response
276+ . extensions ( )
277+ . get :: < DelayedTemplateRender > ( )
278+ . map ( |render| render. cpu_intensive_rendering )
279+ . unwrap_or ( false ) ;
280+
281+ if cpu_intensive_rendering {
282+ spawn_blocking ( || render_response ( response, templates, csp_nonce) )
283+ . await
284+ . expect ( "tokio task join error when rendering templates" )
285+ } else {
286+ render_response ( response, templates, csp_nonce)
287+ }
243288}
0 commit comments