Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions desktop/src-tauri/src/media_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ async fn proxy_handler(AxumState(state): AxumState<ProxyState>, req: Request) ->
"content-range",
"accept-ranges",
"content-length",
// Cache-related headers — let WKWebView's HTTP cache do its job so
// images don't re-fetch on every channel switch. Media URLs are
// content-addressed (sha256 in path), so the relay sends
// `Cache-Control: public, max-age=31536000, immutable` and we
// forward it verbatim. `etag`/`last-modified` are forwarded for
// future-proofing if upstream ever adds them.
"cache-control",
"etag",
"last-modified",
] {
if let Some(val) = resp.headers().get(*key) {
if let Ok(v) = HeaderValue::from_bytes(val.as_bytes()) {
Expand Down Expand Up @@ -205,6 +214,27 @@ pub async fn handle_sprout_media(
.and_then(|v| v.to_str().ok())
.map(|s| s.to_string());

// Propagate cache-related headers so WKWebView's HTTP cache
// can avoid re-fetching content-addressed media on every
// channel switch. The relay sends
// `Cache-Control: public, max-age=31536000, immutable`;
// `etag`/`last-modified` are forwarded if upstream supplies them.
let cache_control = resp
.headers()
.get("cache-control")
.and_then(|v| v.to_str().ok())
.map(|s| s.to_string());
let etag = resp
.headers()
.get("etag")
.and_then(|v| v.to_str().ok())
.map(|s| s.to_string());
let last_modified = resp
.headers()
.get("last-modified")
.and_then(|v| v.to_str().ok())
.map(|s| s.to_string());

// OOM guard: if this is a non-range GET and the upstream body is
// larger than our cap, bail with 413 instead of buffering into RAM.
// Tauri's protocol handler requires Vec<u8> so we can't truly stream.
Expand Down Expand Up @@ -235,6 +265,15 @@ pub async fn handle_sprout_media(
if let Some(ref cl) = content_length {
builder = builder.header("content-length", cl);
}
if let Some(ref cc) = cache_control {
builder = builder.header("cache-control", cc);
}
if let Some(ref e) = etag {
builder = builder.header("etag", e);
}
if let Some(ref lm) = last_modified {
builder = builder.header("last-modified", lm);
}
builder
.body(bytes.to_vec())
.unwrap_or_else(|_| error_response(500, "response build failed"))
Expand Down
Loading