30 lines
8.3 KiB
HTML
30 lines
8.3 KiB
HTML
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="A loopback HTTP server for locally downloaded media."><title>jellytau_lib::media_server - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-17e0aaed.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="jellytau_lib" data-themes="" data-resource-suffix="" data-rustdoc-version="1.97.1 (8bab26f4f 2026-07-14)" data-channel="1.97.1" data-search-js="search-fd9372ac.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-fcd733ba.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-f7c3ffd8.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><a class="skip-main-content" href="#main-content">Skip to main content</a><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">Module media_server</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../jellytau_lib/index.html">jellytau_<wbr>lib</a><span class="version">0.11.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module media_<wbr>server</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li><li><a href="#enums" title="Enums">Enums</a></li><li><a href="#constants" title="Constants">Constants</a></li><li><a href="#functions" title="Functions">Functions</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate jellytau_<wbr>lib</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">jellytau_lib</a></div><h1>Module <span>media_<wbr>server</span> <button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/jellytau_lib/media_server.rs.html#1-588">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>A loopback HTTP server for locally downloaded media.</p>
|
||
<p>Tauri’s built-in <code>asset</code> protocol cannot serve a downloaded film to the
|
||
webview. Its response to a request <em>without</em> a <code>Range</code> header reads the whole
|
||
file into a <code>Vec<u8></code>, and it only advertises <code>Accept-Ranges: bytes</code> 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 <code>PIPELINE_ERROR_READ</code> after ~31s, which reached the user as
|
||
“downloaded video does not play offline”.</p>
|
||
<p>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 <code>Range</code> to a custom
|
||
scheme, which differs between Android and the desktop webviews.</p>
|
||
<p>Two things confine it, because <strong>loopback is shared between apps on
|
||
Android</strong> — any other installed app can connect to this port:</p>
|
||
<ul>
|
||
<li>it binds <code>127.0.0.1</code> only, so nothing off-device can reach it; and</li>
|
||
<li>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.</li>
|
||
</ul>
|
||
<p>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.</p>
|
||
<p>TRACES: UR-071 | DR-137 | UT-127</p>
|
||
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.MediaServer.html" title="struct jellytau_lib::media_server::MediaServer">Media<wbr>Server</a></dt><dd>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.</dd><dt><a class="struct" href="struct.MediaServerWrapper.html" title="struct jellytau_lib::media_server::MediaServerWrapper">Media<wbr>Server<wbr>Wrapper</a></dt><dd>Managed state. <code>None</code> when the server could not bind — local playback then
|
||
fails with a clear error instead of the app refusing to start.</dd><dt><a class="struct" href="struct.Span.html" title="struct jellytau_lib::media_server::Span">Span</a></dt><dd>The byte range a response should carry. <code>end</code> is inclusive.</dd></dl><h2 id="enums" class="section-header">Enums<a href="#enums" class="anchor">§</a></h2><dl class="item-table"><dt><a class="enum" href="enum.Resolved.html" title="enum jellytau_lib::media_server::Resolved">Resolved</a></dt><dd>What a request path resolved to, before any file is touched.</dd></dl><h2 id="constants" class="section-header">Constants<a href="#constants" class="anchor">§</a></h2><dl class="item-table"><dt><a class="constant" href="constant.CHUNK_LEN.html" title="constant jellytau_lib::media_server::CHUNK_LEN">CHUNK_<wbr>LEN</a><span title="Restricted Visibility"> 🔒</span> </dt><dd>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.</dd></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.content_type.html" title="fn jellytau_lib::media_server::content_type">content_<wbr>type</a><span title="Restricted Visibility"> 🔒</span> </dt><dd>Guess a content type.</dd><dt><a class="fn" href="fn.empty.html" title="fn jellytau_lib::media_server::empty">empty</a><span title="Restricted Visibility"> 🔒</span> </dt><dt><a class="fn" href="fn.handle.html" title="fn jellytau_lib::media_server::handle">handle</a><span title="Restricted Visibility"> 🔒</span> </dt><dt><a class="fn" href="fn.header.html" title="fn jellytau_lib::media_server::header">header</a><span title="Restricted Visibility"> 🔒</span> </dt><dt><a class="fn" href="fn.resolve_path.html" title="fn jellytau_lib::media_server::resolve_path">resolve_<wbr>path</a></dt><dd>Resolve a percent-encoded request path to a file inside <code>root</code>.</dd><dt><a class="fn" href="fn.route.html" title="fn jellytau_lib::media_server::route">route</a><span title="Restricted Visibility"> 🔒</span> </dt><dd>Check the token and resolve the path, or return the status to answer with.</dd><dt><a class="fn" href="fn.span_for.html" title="fn jellytau_lib::media_server::span_for">span_<wbr>for</a></dt><dd>Decide which span to send for a <code>Range</code> header (or its absence).</dd><dt><a class="fn" href="fn.start.html" title="fn jellytau_lib::media_server::start">start</a></dt><dd>Bind to an ephemeral loopback port and start serving <code>root</code> in a background
|
||
thread.</dd></dl></section></div></main></body></html> |