up
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { createReadStream } from 'node:fs'
|
||||
import { Readable } from 'node:stream'
|
||||
import type { PackageStore } from './package-store.js'
|
||||
import { parseRange } from './range.js'
|
||||
|
||||
export async function packageMediaResponse(
|
||||
store: PackageStore,
|
||||
request: Request,
|
||||
): Promise<Response> {
|
||||
const url = new URL(request.url)
|
||||
const match = /^\/packages\/([a-f0-9]{64})\/([a-f0-9]{64})$/.exec(url.pathname)
|
||||
if (url.host !== 'app' || request.method !== 'GET' || !match)
|
||||
return new Response(null, { status: 404 })
|
||||
try {
|
||||
const file = await store.localFile(match[1]!, match[2]!)
|
||||
const rangeHeader = request.headers.get('range')
|
||||
const range = parseRange(rangeHeader, file.size)
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': file.mime,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Cache-Control': 'no-store',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Security-Policy': "default-src 'none'; frame-ancestors 'none'; sandbox",
|
||||
}
|
||||
if (!range)
|
||||
return new Response(null, {
|
||||
status: 416,
|
||||
headers: { ...headers, 'Content-Range': `bytes */${file.size}` },
|
||||
})
|
||||
headers['Content-Length'] = String(range.end - range.start + 1)
|
||||
if (rangeHeader) headers['Content-Range'] = `bytes ${range.start}-${range.end}/${file.size}`
|
||||
const stream = createReadStream(file.path, range)
|
||||
const abort = () => stream.destroy()
|
||||
request.signal.addEventListener('abort', abort, { once: true })
|
||||
stream.on('close', () => request.signal.removeEventListener('abort', abort))
|
||||
if (request.signal.aborted) stream.destroy()
|
||||
return new Response(Readable.toWeb(stream) as ReadableStream<Uint8Array>, {
|
||||
status: rangeHeader ? 206 : 200,
|
||||
headers,
|
||||
})
|
||||
} catch {
|
||||
return new Response(null, { status: 404 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user