Files
fx-test/fluxer_media_proxy/src/lib/HttpUtils.ts
2026-03-13 09:47:47 +01:00

68 lines
2.2 KiB
TypeScript

/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {Context} from 'hono';
export const parseRange = (rangeHeader: string | null, fileSize: number) => {
if (!rangeHeader) return null;
const matches = rangeHeader.match(/bytes=(\d*)-(\d*)/);
if (!matches) return null;
const start = matches[1] ? Number.parseInt(matches[1], 10) : 0;
const end = matches[2] ? Number.parseInt(matches[2], 10) : fileSize - 1;
return start >= fileSize || end >= fileSize || start > end ? null : {start, end};
};
export const setHeaders = (
ctx: Context,
size: number,
contentType: string,
range: {start: number; end: number} | null,
lastModified?: Date,
) => {
const isStreamableMedia = contentType.startsWith('video/') || contentType.startsWith('audio/');
const headers = {
'Accept-Ranges': 'bytes',
'Access-Control-Allow-Origin': '*',
'Cache-Control': isStreamableMedia
? 'public, max-age=31536000, no-transform, immutable'
: 'public, max-age=31536000',
'Content-Type': contentType,
Date: new Date().toUTCString(),
Expires: new Date(Date.now() + 31536000000).toUTCString(),
'Last-Modified': lastModified?.toUTCString() ?? new Date().toUTCString(),
Vary: 'Accept-Encoding, Range',
};
Object.entries(headers).forEach(([k, v]) => {
ctx.header(k, v);
});
if (range) {
const length = range.end - range.start + 1;
ctx.status(206);
ctx.header('Content-Length', length.toString());
ctx.header('Content-Range', `bytes ${range.start}-${range.end}/${size}`);
} else {
ctx.header('Content-Length', size.toString());
}
};