mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
feat(html-view): answer Range requests through the shared sendFileBody()
A rendered page's own <video> or <audio> could not seek, because the route streamed a plain 200 without Accept-Ranges. sendFileBody() and localFileSource() are now exported from file-routes.ts and the serving route uses them, so it advertises Accept-Ranges and answers a Range with 206 + Content-Range (or 416), exactly like file-raw, the attachment raw route and /api/download. The body sender hijacks the reply and copies every header set before it (the sandbox CSP, CORS, no-store), which the new test pins on a 206. Media types stay in ASSET_TYPES: with Range support they work, and they are served under the same sandbox CSP as everything else. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
bc940a3953
commit
fa23f8be2a
5 files changed
+37
-8
No files matched your search
@@ -94,6 +94,28 @@ describe('html-view routes', () => {
|
||||
expect(res.body).toBe('<h1>hi</h1>');
|
||||
});
|
||||
|
||||
it('answers Range requests, so a page can seek its own media', async () => {
|
||||
writeFileSync(join(workspace, 'clip.mp4'), '0123456789');
|
||||
const base = (await openUrl()).replace(/index\.html$/, '');
|
||||
const full = await harness.app.inject({ method: 'GET', url: `${base}clip.mp4` });
|
||||
expect(full.statusCode).toBe(200);
|
||||
expect(full.headers['accept-ranges']).toBe('bytes');
|
||||
expect(full.headers['content-length']).toBe('10');
|
||||
|
||||
const part = await harness.app.inject({ method: 'GET', url: `${base}clip.mp4`, headers: { range: 'bytes=2-5' } });
|
||||
expect(part.statusCode).toBe(206);
|
||||
expect(part.headers['content-range']).toBe('bytes 2-5/10');
|
||||
expect(part.body).toBe('2345');
|
||||
// Every header the route sets survives the hijacked body sender.
|
||||
expect(part.headers['content-type']).toBe('video/mp4');
|
||||
expect(String(part.headers['content-security-policy'])).toMatch(/^sandbox /);
|
||||
expect(part.headers['access-control-allow-origin']).toBe('*');
|
||||
expect(part.headers['cache-control']).toBe('no-store');
|
||||
|
||||
const beyond = await harness.app.inject({ method: 'GET', url: `${base}clip.mp4`, headers: { range: 'bytes=50-' } });
|
||||
expect(beyond.statusCode).toBe(416);
|
||||
});
|
||||
|
||||
it('serves sibling assets, including subdirectories', async () => {
|
||||
const base = (await openUrl()).replace(/index\.html$/, '');
|
||||
expect((await harness.app.inject({ method: 'GET', url: `${base}assets/app.css` })).statusCode).toBe(200);
|
||||
|
||||
Reference in new issue
Block a user