Files
Nele-Till-Hochzeit/patch_range.js
T

74 lines
2.3 KiB
JavaScript

const fs = require('fs');
let route = fs.readFileSync('src/app/api/media/[...path]/route.ts', 'utf8');
const rangeLogic = `
// Get file stats for Content-Length
const stat = await fs.promises.stat(filePath);
const fileSize = stat.size;
// Handle Range Requests (CRITICAL for video streaming in Safari/Chrome)
const rangeHeader = request.headers.get('range');
let start = 0;
let end = fileSize - 1;
let isPartial = false;
if (rangeHeader) {
const parts = rangeHeader.replace(/bytes=/, '').split('-');
const partialStart = parts[0];
const partialEnd = parts[1];
start = parseInt(partialStart, 10);
end = partialEnd ? parseInt(partialEnd, 10) : fileSize - 1;
if (start >= fileSize) {
return new NextResponse('Requested range not satisfiable', { status: 416 });
}
isPartial = true;
}
const contentLength = (end - start) + 1;
// Build response headers
const contentType = getSafeContentType(contentTypeExt);
const headers = new Headers();
headers.set('Content-Type', contentType);
headers.set('Content-Length', contentLength.toString());
headers.set('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');
headers.set('Accept-Ranges', 'bytes');
if (isPartial) {
headers.set('Content-Range', \`bytes \${start}-\${end}/\${fileSize}\`);
}
// SVG: force download to prevent XSS
if (contentType === 'image/svg+xml') {
headers.set('Content-Disposition', \`attachment; filename="\${path.basename(relativePath)}"\`);
}
// Stream the file chunk
const fileStream = fs.createReadStream(filePath, { start, end });
const webStream = new ReadableStream({
start(controller) {
fileStream.on('data', (chunk) => controller.enqueue(new Uint8Array(chunk)));
fileStream.on('end', () => controller.close());
fileStream.on('error', (err) => controller.error(err));
},
cancel() {
fileStream.destroy();
},
});
return new NextResponse(webStream, {
status: isPartial ? 206 : 200,
headers
});
`;
route = route.replace(
/\/\/ Get file stats for Content-Length[\s\S]+return new NextResponse\(webStream, \{ headers \}\);/,
rangeLogic.trim()
);
fs.writeFileSync('src/app/api/media/[...path]/route.ts', route, 'utf8');