1
1
use super :: TemplateData ;
2
2
use crate :: {
3
3
ctry,
4
+ utils:: spawn_blocking,
4
5
web:: { cache:: CachePolicy , csp:: Csp , error:: AxumNope } ,
5
6
} ;
6
- use anyhow:: anyhow ;
7
+ use anyhow:: Error ;
7
8
use axum:: {
8
9
body:: { boxed, Body } ,
9
10
http:: Request as AxumRequest ,
10
11
middleware:: Next ,
11
12
response:: { IntoResponse , Response as AxumResponse } ,
12
13
} ;
14
+ use futures_util:: future:: { BoxFuture , FutureExt } ;
13
15
use http:: header:: CONTENT_LENGTH ;
14
16
use iron:: {
15
17
headers:: { ContentType , Link , LinkValue , RelationType } ,
@@ -20,7 +22,6 @@ use iron::{
20
22
use serde:: Serialize ;
21
23
use std:: { borrow:: Cow , sync:: Arc } ;
22
24
use tera:: Context ;
23
- use tokio:: task:: spawn_blocking;
24
25
25
26
/// When making using a custom status, use a closure that coerces to a `fn(&Self) -> Status`
26
27
#[ macro_export]
@@ -221,36 +222,56 @@ fn render_response(
221
222
mut response : AxumResponse ,
222
223
templates : Arc < TemplateData > ,
223
224
csp_nonce : String ,
224
- ) -> AxumResponse {
225
- if let Some ( render) = response. extensions ( ) . get :: < DelayedTemplateRender > ( ) {
226
- let tera = & templates. templates ;
227
- let mut context = render. context . clone ( ) ;
228
- context. insert ( "csp_nonce" , & csp_nonce) ;
229
-
230
- let rendered = match tera. render ( & render. template , & context) {
231
- Ok ( content) => content,
232
- Err ( err) => {
233
- if response. status ( ) . is_server_error ( ) {
234
- // avoid infinite loop if error.html somehow fails to load
235
- panic ! ( "error while serving error page: {:?}" , err) ;
236
- } else {
237
- return render_response (
238
- AxumNope :: InternalError ( anyhow ! ( err) ) . into_response ( ) ,
239
- templates,
240
- csp_nonce,
241
- ) ;
225
+ ) -> BoxFuture < ' static , AxumResponse > {
226
+ async move {
227
+ if let Some ( render) = response. extensions_mut ( ) . remove :: < DelayedTemplateRender > ( ) {
228
+ let DelayedTemplateRender {
229
+ template,
230
+ mut context,
231
+ cpu_intensive_rendering,
232
+ } = render;
233
+ context. insert ( "csp_nonce" , & csp_nonce) ;
234
+
235
+ let rendered = if cpu_intensive_rendering {
236
+ spawn_blocking ( {
237
+ let templates = templates. clone ( ) ;
238
+ move || Ok ( templates. templates . render ( & template, & context) ?)
239
+ } )
240
+ . await
241
+ } else {
242
+ templates
243
+ . templates
244
+ . render ( & template, & context)
245
+ . map_err ( Error :: new)
246
+ } ;
247
+
248
+ let rendered = match rendered {
249
+ Ok ( content) => content,
250
+ Err ( err) => {
251
+ if response. status ( ) . is_server_error ( ) {
252
+ // avoid infinite loop if error.html somehow fails to load
253
+ panic ! ( "error while serving error page: {:?}" , err) ;
254
+ } else {
255
+ return render_response (
256
+ AxumNope :: InternalError ( err) . into_response ( ) ,
257
+ templates,
258
+ csp_nonce,
259
+ )
260
+ . await ;
261
+ }
242
262
}
243
- }
244
- } ;
245
- let content_length = rendered . len ( ) ;
246
- * response . body_mut ( ) = boxed ( Body :: from ( rendered ) ) ;
247
- response
248
- . headers_mut ( )
249
- . insert ( CONTENT_LENGTH , content_length . into ( ) ) ;
250
- response
251
- } else {
252
- response
263
+ } ;
264
+ let content_length = rendered . len ( ) ;
265
+ * response . body_mut ( ) = boxed ( Body :: from ( rendered ) ) ;
266
+ response
267
+ . headers_mut ( )
268
+ . insert ( CONTENT_LENGTH , content_length . into ( ) ) ;
269
+ response
270
+ } else {
271
+ response
272
+ }
253
273
}
274
+ . boxed ( )
254
275
}
255
276
256
277
pub ( crate ) async fn render_templates_middleware < B > (
@@ -272,17 +293,5 @@ pub(crate) async fn render_templates_middleware<B>(
272
293
273
294
let response = next. run ( req) . await ;
274
295
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
- }
296
+ render_response ( response, templates, csp_nonce) . await
288
297
}
0 commit comments