@@ -19,7 +19,8 @@ use iron::{
19
19
} ;
20
20
use serde:: Serialize ;
21
21
use std:: { borrow:: Cow , sync:: Arc } ;
22
- use tera:: { Context , Tera } ;
22
+ use tera:: Context ;
23
+ use tokio:: task:: spawn_blocking;
23
24
24
25
/// When making using a custom status, use a closure that coerces to a `fn(&Self) -> Status`
25
26
#[ macro_export]
@@ -61,11 +62,28 @@ macro_rules! impl_webpage {
61
62
62
63
#[ macro_export]
63
64
macro_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
+ ) ;
66
78
} ;
67
79
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
+ ) => {
69
87
impl axum:: response:: IntoResponse for $page
70
88
{
71
89
fn into_response( self ) -> :: axum:: response:: Response {
@@ -76,6 +94,12 @@ macro_rules! impl_axum_webpage {
76
94
ct = $content_type;
77
95
) ?
78
96
97
+ #[ allow( unused_mut, unused_assignments) ]
98
+ let mut cpu_intensive_rendering = false ;
99
+ $(
100
+ cpu_intensive_rendering = $cpu_intensive_rendering;
101
+ ) ?
102
+
79
103
let mut response = :: axum:: http:: Response :: builder( )
80
104
. header( :: axum:: http:: header:: CONTENT_TYPE , ct)
81
105
$(
@@ -96,6 +120,7 @@ macro_rules! impl_axum_webpage {
96
120
let template: fn ( & Self ) -> :: std:: borrow:: Cow <' static , str > = $template;
97
121
template( & self ) . to_string( )
98
122
} ,
123
+ cpu_intensive_rendering,
99
124
} ) ;
100
125
response
101
126
}
@@ -189,14 +214,20 @@ pub trait WebPage: Serialize + Sized {
189
214
pub ( crate ) struct DelayedTemplateRender {
190
215
pub template : String ,
191
216
pub context : Context ,
217
+ pub cpu_intensive_rendering : bool ,
192
218
}
193
219
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 {
195
225
if let Some ( render) = response. extensions ( ) . get :: < DelayedTemplateRender > ( ) {
226
+ let tera = & templates. templates ;
196
227
let mut context = render. context . clone ( ) ;
197
228
context. insert ( "csp_nonce" , & csp_nonce) ;
198
229
199
- let rendered = match templates . render ( & render. template , & context) {
230
+ let rendered = match tera . render ( & render. template , & context) {
200
231
Ok ( content) => content,
201
232
Err ( err) => {
202
233
if response. status ( ) . is_server_error ( ) {
@@ -239,5 +270,19 @@ pub(crate) async fn render_templates_middleware<B>(
239
270
. nonce ( )
240
271
. to_owned ( ) ;
241
272
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
+ }
243
288
}
0 commit comments