Show artwork up to 20 MB, and remember and log what failed (#169)
Five Glass Cannon Network feeds name Patreon covers of about 7 MB, over the 5 MB limit on /api/art. Each page load fetched them all again, refused them, and logged a 502 per cover, about 84 a day, with nothing in the log to say which image or why: the reason went only to the browser. The limit is now 20 MB, a failure is answered from memory for an hour, and the fetch failure is logged with its address and reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
16
src/web.rs
16
src/web.rs
@@ -1893,10 +1893,11 @@ struct ArtQuery {
|
||||
/// time it is fetched from the publisher and kept on disk (`art`, up to `art_cache_mb`), so
|
||||
/// later it is fast, the publisher is not asked on every visit, and it outlives the publisher's
|
||||
/// server. Only an address some feed or item names as its artwork, and only an image up to
|
||||
/// 5 MB, so the route cannot be pointed at anything else. It began as a way round http-only
|
||||
/// 20 MB, so the route cannot be pointed at anything else. It began as a way round http-only
|
||||
/// artwork on the https page (#90).
|
||||
async fn art(State(state): State<WebState>, Query(q): Query<ArtQuery>) -> Response {
|
||||
const MAX: usize = 5 << 20;
|
||||
// 5 MB turned away the Glass Cannon Network's covers, 7 MB PNGs (#169).
|
||||
const MAX: usize = 20 << 20;
|
||||
let web = q.u.starts_with("http://") || q.u.starts_with("https://");
|
||||
if !web || !state.ctx.db.names_image(&q.u).await.unwrap_or(false) {
|
||||
return (StatusCode::NOT_FOUND, "no feed names that artwork").into_response();
|
||||
@@ -1906,6 +1907,9 @@ async fn art(State(state): State<WebState>, Query(q): Query<ArtQuery>) -> Respon
|
||||
if keep && let Some((kind, body)) = crate::art::read(&file) {
|
||||
return art_response(kind, body);
|
||||
}
|
||||
if let Some(why) = crate::art::failed(&q.u) {
|
||||
return (StatusCode::BAD_GATEWAY, why).into_response();
|
||||
}
|
||||
let got = async {
|
||||
let mut r = state.ctx.client.get(&q.u).timeout(crate::feed::FEED_TIMEOUT).send().await?.error_for_status()?;
|
||||
let kind = r.headers().get(header::CONTENT_TYPE).and_then(|v| v.to_str().ok()).unwrap_or("").to_owned();
|
||||
@@ -1924,7 +1928,13 @@ async fn art(State(state): State<WebState>, Query(q): Query<ArtQuery>) -> Respon
|
||||
}
|
||||
art_response(kind, body)
|
||||
}
|
||||
Err(e) => (StatusCode::BAD_GATEWAY, format!("{e:#}")).into_response(),
|
||||
Err(e) => {
|
||||
let why = format!("{e:#}");
|
||||
// The access line says only that it failed, not which image or why (#169).
|
||||
tracing::warn!(url = %q.u, error = %why, "could not fetch artwork");
|
||||
crate::art::fail(&q.u, &why);
|
||||
(StatusCode::BAD_GATEWAY, why).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user