11use super :: TemplateData ;
22use crate :: {
33 ctry,
4+ utils:: spawn_blocking,
45 web:: { cache:: CachePolicy , csp:: Csp , error:: AxumNope } ,
56} ;
6- use anyhow:: anyhow ;
7+ use anyhow:: Error ;
78use axum:: {
89 body:: { boxed, Body } ,
910 http:: Request as AxumRequest ,
1011 middleware:: Next ,
1112 response:: { IntoResponse , Response as AxumResponse } ,
1213} ;
14+ use futures_util:: future:: { BoxFuture , FutureExt } ;
1315use http:: header:: CONTENT_LENGTH ;
1416use iron:: {
1517 headers:: { ContentType , Link , LinkValue , RelationType } ,
@@ -20,7 +22,6 @@ use iron::{
2022use serde:: Serialize ;
2123use std:: { borrow:: Cow , sync:: Arc } ;
2224use tera:: Context ;
23- use tokio:: task:: spawn_blocking;
2425
2526/// When making using a custom status, use a closure that coerces to a `fn(&Self) -> Status`
2627#[ macro_export]
@@ -221,36 +222,56 @@ fn render_response(
221222 mut response : AxumResponse ,
222223 templates : Arc < TemplateData > ,
223224 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+ }
242262 }
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+ }
253273 }
274+ . boxed ( )
254275}
255276
256277pub ( crate ) async fn render_templates_middleware < B > (
@@ -272,17 +293,5 @@ pub(crate) async fn render_templates_middleware<B>(
272293
273294 let response = next. run ( req) . await ;
274295
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
288297}
0 commit comments