Transform images + placeholders
Some checks failed
CI / Check typos (push) Successful in 8s
CI / Check links (push) Failing after 10s
CI / Clippy (push) Successful in 56s
CI / Build and test (push) Successful in 1m22s
CI / Build container (push) Successful in 1m4s
CI / Deploy on waypoint (push) Successful in 46s
Some checks failed
CI / Check typos (push) Successful in 8s
CI / Check links (push) Failing after 10s
CI / Clippy (push) Successful in 56s
CI / Build and test (push) Successful in 1m22s
CI / Build container (push) Successful in 1m4s
CI / Deploy on waypoint (push) Successful in 46s
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use axum::http::{
|
||||
HeaderMap, HeaderValue, StatusCode,
|
||||
header::{self},
|
||||
};
|
||||
use std::pin::Pin;
|
||||
use axum::http::{HeaderMap, StatusCode};
|
||||
use chrono::TimeDelta;
|
||||
use pixel_transform::TransformerChain;
|
||||
use std::{pin::Pin, str::FromStr};
|
||||
use toolbox::mime::MimeType;
|
||||
use tracing::{error, trace};
|
||||
|
||||
use crate::{Rendered, RenderedBody, RequestContext, Servable};
|
||||
|
||||
@@ -15,30 +15,102 @@ pub struct StaticAsset {
|
||||
impl Servable for StaticAsset {
|
||||
fn render<'a>(
|
||||
&'a self,
|
||||
_ctx: &'a RequestContext,
|
||||
ctx: &'a RequestContext,
|
||||
) -> Pin<Box<dyn Future<Output = crate::Rendered> + 'a + Send + Sync>> {
|
||||
Box::pin(async {
|
||||
let mut headers = HeaderMap::with_capacity(3);
|
||||
let ttl = Some(TimeDelta::days(30));
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
headers.insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_str(&self.mime.to_string()).unwrap(),
|
||||
);
|
||||
// Automatically provide transformation if this is an image
|
||||
let is_image = TransformerChain::mime_is_image(&self.mime);
|
||||
|
||||
headers.insert(
|
||||
header::CACHE_CONTROL,
|
||||
HeaderValue::from_str(&format!("immutable, public, max-age={}", 60 * 60 * 24 * 30))
|
||||
.unwrap(),
|
||||
);
|
||||
let transform = match (is_image, ctx.query.get("t")) {
|
||||
(false, _) | (_, None) => None,
|
||||
|
||||
return Rendered {
|
||||
code: StatusCode::OK,
|
||||
headers,
|
||||
body: RenderedBody::Static(self.bytes),
|
||||
ttl: None,
|
||||
immutable: true,
|
||||
(true, Some(x)) => match TransformerChain::from_str(x) {
|
||||
Ok(x) => Some(x),
|
||||
Err(err) => {
|
||||
return Rendered {
|
||||
code: StatusCode::BAD_REQUEST,
|
||||
body: RenderedBody::String(err),
|
||||
ttl,
|
||||
immutable: true,
|
||||
|
||||
headers: HeaderMap::new(),
|
||||
mime: None,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match transform {
|
||||
Some(transform) => {
|
||||
trace!(message = "Transforming image", ?transform);
|
||||
|
||||
let task = {
|
||||
let mime = Some(self.mime.clone());
|
||||
let bytes = self.bytes;
|
||||
tokio::task::spawn_blocking(move || {
|
||||
transform.transform_bytes(bytes, mime.as_ref())
|
||||
})
|
||||
};
|
||||
|
||||
let res = match task.await {
|
||||
Ok(x) => x,
|
||||
Err(error) => {
|
||||
error!(message = "Error while transforming image", ?error);
|
||||
return Rendered {
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR,
|
||||
body: RenderedBody::String(format!(
|
||||
"Error while transforming image: {error:?}"
|
||||
)),
|
||||
ttl: None,
|
||||
immutable: true,
|
||||
|
||||
headers: HeaderMap::new(),
|
||||
mime: None,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
match res {
|
||||
Ok((mime, bytes)) => {
|
||||
return Rendered {
|
||||
code: StatusCode::OK,
|
||||
body: RenderedBody::Bytes(bytes),
|
||||
ttl,
|
||||
immutable: true,
|
||||
|
||||
headers: HeaderMap::new(),
|
||||
mime: Some(mime),
|
||||
};
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
return Rendered {
|
||||
code: StatusCode::INTERNAL_SERVER_ERROR,
|
||||
body: RenderedBody::String(format!("{err}")),
|
||||
ttl,
|
||||
immutable: true,
|
||||
|
||||
headers: HeaderMap::new(),
|
||||
mime: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None => {
|
||||
return Rendered {
|
||||
code: StatusCode::OK,
|
||||
body: RenderedBody::Static(self.bytes),
|
||||
ttl,
|
||||
immutable: true,
|
||||
|
||||
headers: HeaderMap::new(),
|
||||
mime: Some(self.mime.clone()),
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user