Skip to main content

## Module media_server

Source
Expand description

A loopback HTTP server for locally downloaded media.

Tauri’s built-in `asset` protocol cannot serve a downloaded film to the webview. Its response to a request without a `Range` header reads the whole file into a `Vec<u8>`, and it only advertises `Accept-Ranges: bytes` from inside the range branch — so the first request never learns ranges are available and a multi-gigabyte body is attempted instead. Chromium abandoned it with `PIPELINE_ERROR_READ` after ~31s, which reached the user as “downloaded video does not play offline”.

Serving over real HTTP on 127.0.0.1 rather than a custom URI scheme is deliberate: it makes range support a property of the transport instead of depending on whether a platform’s webview forwards `Range` to a custom scheme, which differs between Android and the desktop webviews.

Two things confine it, because loopback is shared between apps on Android — any other installed app can connect to this port:

- it binds `127.0.0.1` only, so nothing off-device can reach it; and
- every URL carries a random per-session token, so another app cannot guess a working URL, and paths are confined to the app data directory even if one did.

Phase 1 serves local files only. The same origin is the intended home for remote passthrough (and download-while-watching) later; see the stage-2 spec.

TRACES: UR-071 | DR-137 | UT-127

## Structs§

MediaServer
  A running server. Dropping this does not stop the thread; the server lives for the life of the process by design, since playback can start at any time.
MediaServerWrapper
  Managed state. `None` when the server could not bind — local playback then fails with a clear error instead of the app refusing to start.
Span
  The byte range a response should carry. `end` is inclusive.

## Enums§

Resolved
  What a request path resolved to, before any file is touched.

## Constants§

CHUNK_LEN 🔒
  Bytes per response. Large enough that a film needs relatively few round trips, small enough that one response is never a memory problem on a phone. Tauri’s asset protocol uses 1 MiB; 4 MiB quarters the request count for the multi-gigabyte files this exists to serve.

## Functions§

content_type 🔒
  Guess a content type.
empty 🔒
handle 🔒
header 🔒
resolve_path
  Resolve a percent-encoded request path to a file inside `root`.
route 🔒
  Check the token and resolve the path, or return the status to answer with.
span_for
  Decide which span to send for a `Range` header (or its absence).
start
  Bind to an ephemeral loopback port and start serving `root` in a background thread.