fix: cache immutable blobs served from /files
Page and cover blobs are content-addressed by unguessable, immutable keys, but /files sent no Cache-Control, so the browser refetched on every reader open — defeating the whole-chapter and next-chapter preloading (and re- proxying every byte through the node server in prod). Send `Cache-Control: public, max-age=31536000, immutable`. Bump to 0.124.3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2
backend/Cargo.lock
generated
2
backend/Cargo.lock
generated
@@ -1558,7 +1558,7 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mangalord"
|
name = "mangalord"
|
||||||
version = "0.124.2"
|
version = "0.124.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argon2",
|
"argon2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mangalord"
|
name = "mangalord"
|
||||||
version = "0.124.2"
|
version = "0.124.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "mangalord"
|
default-run = "mangalord"
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ async fn serve(State(state): State<AppState>, Path(key): Path<String>) -> AppRes
|
|||||||
HeaderName::from_static("x-content-type-options"),
|
HeaderName::from_static("x-content-type-options"),
|
||||||
"nosniff".to_string(),
|
"nosniff".to_string(),
|
||||||
),
|
),
|
||||||
|
// Blobs are content-addressed by unguessable, immutable keys (a
|
||||||
|
// re-upload mints new UUIDs), so a fetched page/cover never changes.
|
||||||
|
// Cache it for a year and mark it `immutable` so browsers skip
|
||||||
|
// revalidation entirely — this is what lets the reader's page and
|
||||||
|
// next-chapter preloading hit cache instead of re-downloading (and
|
||||||
|
// re-proxying every byte through the SvelteKit node server in prod).
|
||||||
|
(
|
||||||
|
header::CACHE_CONTROL,
|
||||||
|
"public, max-age=31536000, immutable".to_string(),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
Ok((headers, Body::from_stream(file.stream)).into_response())
|
Ok((headers, Body::from_stream(file.stream)).into_response())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,13 @@ async fn files_endpoint_streams_in_multiple_frames(pool: PgPool) {
|
|||||||
resp.headers().get("x-content-type-options").unwrap(),
|
resp.headers().get("x-content-type-options").unwrap(),
|
||||||
"nosniff"
|
"nosniff"
|
||||||
);
|
);
|
||||||
|
// Blobs are content-addressed by unguessable, immutable keys, so they're
|
||||||
|
// safe to cache forever — this is what makes the reader's page + next-
|
||||||
|
// chapter preloading actually hit cache instead of re-downloading.
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get(header::CACHE_CONTROL).unwrap(),
|
||||||
|
"public, max-age=31536000, immutable"
|
||||||
|
);
|
||||||
|
|
||||||
let mut body = resp.into_body();
|
let mut body = resp.into_body();
|
||||||
let mut frames = 0usize;
|
let mut frames = 0usize;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mangalord-frontend",
|
"name": "mangalord-frontend",
|
||||||
"version": "0.124.2",
|
"version": "0.124.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user