fix: fall back to the original when a thumbnail fails to decode
A blob with valid magic but a corrupt body passed upload then 500'd on a ?w= thumbnail decode (audit). Fall back to serve_original (streams without decoding) instead. Tested. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -118,9 +118,20 @@ async fn serve_thumbnail(
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
// Resizing is CPU-bound; keep it off the async worker threads.
|
||||
let thumb = tokio::task::spawn_blocking(move || make_thumbnail(&original, width, fmt))
|
||||
let thumb = match tokio::task::spawn_blocking(move || make_thumbnail(&original, width, fmt))
|
||||
.await
|
||||
.map_err(|e| AppError::Other(anyhow::anyhow!("thumbnail task join: {e}")))??;
|
||||
.map_err(|e| AppError::Other(anyhow::anyhow!("thumbnail task join: {e}")))?
|
||||
{
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
// The blob's magic bytes passed upload's sniff but the body won't
|
||||
// decode (corrupt/truncated, or an encoder feature we don't support).
|
||||
// Don't 500 the reader — fall back to streaming the original, which
|
||||
// serves without decoding.
|
||||
tracing::warn!(key, error = %format!("{e:#}"), "thumbnail decode failed; serving original");
|
||||
return serve_original(state, key).await;
|
||||
}
|
||||
};
|
||||
|
||||
// Best-effort cache; a write failure just means we regenerate next time.
|
||||
let _ = state.storage.put(&derived, &thumb).await;
|
||||
|
||||
Reference in New Issue
Block a user