fix: fix unseekable videos on webkit-based browsers

this commit fixes videos not being able to fast-forward/rewind for lack of http headers and 206
status code

fix https://github.com/zyachel/libremdb/issues/26
This commit is contained in:
zyachel 2023-01-14 16:36:20 +05:30
parent cfa8c53d11
commit a32785ce00

View File

@ -2,6 +2,22 @@ import { NextApiRequest, NextApiResponse } from 'next';
import redis from '../../utils/redis'; import redis from '../../utils/redis';
import axiosInstance from '../../utils/axiosInstance'; import axiosInstance from '../../utils/axiosInstance';
const getCleanReqHeaders = (headers: NextApiRequest['headers']) => ({
...(headers.accept && { accept: headers.accept }),
...(headers.range && { range: headers.range }),
...(headers['accept-encoding'] && {
'accept-encoding': headers['accept-encoding'] as string,
}),
});
const resHeadersArr = [
'content-range',
'content-length',
'content-type',
'accept-ranges',
];
// checks if a url is pointing towards a video/image from imdb
const regex = const regex =
/^https:\/\/((m\.)?media-amazon\.com|imdb-video\.media-imdb\.com).*\.(jpg|jpeg|png|mp4|gif|webp).*$/; /^https:\/\/((m\.)?media-amazon\.com|imdb-video\.media-imdb\.com).*\.(jpg|jpeg|png|mp4|gif|webp).*$/;
@ -11,6 +27,7 @@ export default async function handler(
) { ) {
try { try {
const mediaUrl = req.query.url as string | undefined; const mediaUrl = req.query.url as string | undefined;
const requestHeaders = getCleanReqHeaders(req.headers);
// 1. returning if query is illegal // 1. returning if query is illegal
if (!mediaUrl || !regex.test(mediaUrl)) if (!mediaUrl || !regex.test(mediaUrl))
@ -23,9 +40,15 @@ export default async function handler(
if (redis === null) { if (redis === null) {
const mediaRes = await axiosInstance.get(mediaUrl, { const mediaRes = await axiosInstance.get(mediaUrl, {
responseType: 'stream', responseType: 'stream',
headers: requestHeaders,
}); });
res.setHeader('Content-Type', mediaRes.headers['content-type']); // chromium browsers want a 206 response with specific headers. so, we gotta pass them on.
res.statusCode = mediaRes.status;
resHeadersArr.forEach(key => {
const val = mediaRes.headers[key];
if (val) res.setHeader(key, val);
});
mediaRes.data.pipe(res); mediaRes.data.pipe(res);
return; return;
} }
@ -44,7 +67,7 @@ export default async function handler(
responseType: 'arraybuffer', responseType: 'arraybuffer',
}); });
const data = mediaRes.data; const { data } = mediaRes;
// saving in redis for 30 minutes // saving in redis for 30 minutes
await redis!.setex(mediaUrl, 30 * 60, Buffer.from(data)); await redis!.setex(mediaUrl, 30 * 60, Buffer.from(data));