Keep media out of shared caches (#189)
Played from ipodderx.sdf1.net, DeadAir's audio reached ipx as one request with no Range header: Cloudflare caches by extension, deadair.mp3 has one, and /media said nothing about caching, so Cloudflare fetched the whole file and served ranges from its own copy, to anyone Access let in, without the subscriber check (#129). /media/{id} has no extension and was never cached. Cache-Control: private on every media response, the save included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2012,6 +2012,7 @@ async fn media_save(State(state): State<WebState>, Path(id): Path<i64>, user: cr
|
||||
(header::CONTENT_TYPE, kind.to_owned()),
|
||||
(header::CONTENT_LENGTH, len.to_string()),
|
||||
(header::CONTENT_DISPOSITION, format!("attachment; filename*=UTF-8''{name}")),
|
||||
(header::CACHE_CONTROL, "private".to_owned()),
|
||||
],
|
||||
axum::body::Body::from_stream(body),
|
||||
)
|
||||
@@ -2044,7 +2045,12 @@ async fn serve_media(state: WebState, id: i64, user: crate::db::User, req: Reque
|
||||
state.playing.lock().unwrap().remove(&(user.id, enc.feed_id.clone(), enc.guid.clone()));
|
||||
}
|
||||
match ServeFile::new(crate::download::playable(std::path::Path::new(&path))).oneshot(req).await {
|
||||
Ok(r) => r.into_response(),
|
||||
Ok(mut r) => {
|
||||
// Never in a shared cache: Cloudflare kept `deadair.mp3`, by its extension, and served
|
||||
// its copy to anyone Access let in, without the subscriber check above (#189).
|
||||
r.headers_mut().insert(header::CACHE_CONTROL, header::HeaderValue::from_static("private"));
|
||||
r.into_response()
|
||||
}
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user