Skip to content

Download endpoint: no HTTP Range support, broken downloads can't be resumed #153

Description

@rubenhensen

Filed as the download-side counterpart to #136. The earlier triage on #136 assumed Rocket's FileServer already supports HTTP Range, so no server change was needed. That assumption is wrong for Rocket 0.5.

What is wrong

/filedownload is mounted via Rocket's FileServer::from(config.data_dir()) (src/main.rs:1015). Under the hood:

  • FileServer resolves the path and returns a NamedFile.
  • NamedFile::respond_to defers to tokio::fs::File's responder.
  • That responder is Response::build().sized_body(None, self).ok() — a plain 200 OK with Content-Length, no Accept-Ranges, and no handling of an inbound Range request header.

Source: rocket-0.5.1 named_file.rs and response/responder.rs:455.

Consequence

  • Browsers send Range: bytes=...- to resume an interrupted download. Cryptify ignores it and returns the full body with 200.
  • Modern browsers detect the missing Accept-Ranges: bytes and disable the resume button on a failed download. A flaky link on a multi-GB recipient download means the user restarts from byte 0.
  • This is the actual user-visible "download is fragile" symptom referenced in Upload and download sessions are not robust #136.

Possible designs

  1. Custom range-aware handler. Replace the FileServer mount with a route that opens the file, parses Range, and streams a 206 with Content-Range. A small amount of code; no extra dependency if we want to keep the responder narrow.
  2. rocket-seek-stream or equivalent crate. Off-the-shelf Range-aware responder.
  3. Reverse-proxy offload. Put nginx/Caddy in front and let it serve /filedownload directly with native Range support. Operationally simple but assumes the deployment topology — postguard-ops currently exposes cryptify directly per the helm chart.

Option 1 is small and keeps cryptify self-contained, which matches the rest of the codebase.

Out of scope

  • Client-side download UX (progress bar / resume button surfacing) — tracked on the website side: postguard-website#138.
  • Range support for files served while still uploading. The current download flow only serves finalized files, so no interaction.

Suggested next step

Confirm the symptom with a real download (curl with -H 'Range: bytes=100-' against a finalized file — expect 200 + full body, not 206). If confirmed, scope to design #1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions