docs(upload): stop claiming a proxy bandwidth control that does not exist
`get_original`'s comment said bandwidth abuse "belongs at the proxy, where per-connection limits still work", which reads as though the removed per-IP limiter had been replaced by something. It was not: the Caddyfile sets timeouts and no rate or concurrency directive, and the tower stack is TraceLayer alone. Removing the limiter was right — the venue is one NAT address, so that bucket throttled the whole party's feed — but the route is now unbounded, and the comment should say so rather than imply cover. Records the actual cost (no-store plus the derivative fallback plus the nonce'd retry, against a 15-slot pool that upload commits compete for) and the shape a real fix would take: a concurrency semaphore over media streaming, not a request-rate bucket.
This commit is contained in:
@@ -1477,9 +1477,21 @@ async fn stream_media_file(
|
|||||||
///
|
///
|
||||||
/// A per-IP bucket cannot separate "one scraper" from "the entire party" when they share an
|
/// A per-IP bucket cannot separate "one scraper" from "the entire party" when they share an
|
||||||
/// address, and these four media routes are unauthenticated by design (an `<img>` cannot send a
|
/// address, and these four media routes are unauthenticated by design (an `<img>` cannot send a
|
||||||
/// bearer token), so there is no per-user key to move to. Bandwidth abuse belongs at the proxy,
|
/// bearer token), so there is no per-user key to move to. The certain harm outweighed the
|
||||||
/// where per-connection limits still work; the certain harm here outweighed the speculative
|
/// speculative protection.
|
||||||
/// protection.
|
///
|
||||||
|
/// BE HONEST ABOUT WHAT REPLACED IT: nothing did. This used to say "bandwidth abuse belongs at the
|
||||||
|
/// proxy, where per-connection limits still work", which reads as though a control exists there.
|
||||||
|
/// It does not — the `Caddyfile` sets timeouts and no rate or concurrency directive, and the tower
|
||||||
|
/// stack is `TraceLayer` alone. So this route is unbounded, deliberately, and the cost is real
|
||||||
|
/// rather than theoretical: `no-store` below plus the feed's fallback to `/original` for any photo
|
||||||
|
/// whose derivatives are still compressing plus `VirtualFeed`'s nonce'd retry means a hundred open
|
||||||
|
/// feeds can re-fetch full-resolution originals off the same disk Postgres writes WAL to, each one
|
||||||
|
/// also holding a connection from a 15-slot pool that upload commits are competing for.
|
||||||
|
///
|
||||||
|
/// If that needs bounding, the shape that fits is a concurrency semaphore over media streaming
|
||||||
|
/// (like `upload_admission`), NOT a request-rate bucket — the venue is one IP, which is what made
|
||||||
|
/// the previous attempt a self-inflicted outage.
|
||||||
pub async fn get_original(
|
pub async fn get_original(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
|
|||||||
Reference in New Issue
Block a user