Skip to content

Commit 140b5b9

Browse files
Nemo157syphar
authored andcommitted
Move spawn_blocking inside render_response
1 parent 9192aad commit 140b5b9

File tree

1 file changed

+52
-43
lines changed

1 file changed

+52
-43
lines changed

src/web/page/web_page.rs

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use super::TemplateData;
22
use crate::{
33
ctry,
4+
utils::spawn_blocking,
45
web::{cache::CachePolicy, csp::Csp, error::AxumNope},
56
};
6-
use anyhow::anyhow;
7+
use anyhow::Error;
78
use 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};
1315
use http::header::CONTENT_LENGTH;
1416
use iron::{
1517
headers::{ContentType, Link, LinkValue, RelationType},
@@ -20,7 +22,6 @@ use iron::{
2022
use serde::Serialize;
2123
use std::{borrow::Cow, sync::Arc};
2224
use 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

256277
pub(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

Comments
 (0)