mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-04 23:54:28 -07:00
fix(anime): preserve HLS playlist rewriting and fetch timeouts
- Force identity encoding for upstream playlist responses - Keep inactivity timeouts active while streaming response bodies
This commit is contained in:
@@ -3,6 +3,7 @@ import assert from 'node:assert/strict';
|
||||
import http from 'node:http';
|
||||
import net from 'node:net';
|
||||
import type { AddressInfo } from 'node:net';
|
||||
import { gzipSync } from 'node:zlib';
|
||||
import {
|
||||
findTsSyncOffset,
|
||||
rewritePlaylistOrigins,
|
||||
@@ -204,6 +205,31 @@ test('proxy leaves non-TS bodies alone', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('proxy forces identity encoding so playlists remain readable for rewriting', async () => {
|
||||
let upstreamAcceptEncoding: string | undefined;
|
||||
await withProxy(
|
||||
(req, res) => {
|
||||
upstreamAcceptEncoding = req.headers['accept-encoding'];
|
||||
const body = `#EXTM3U\n#EXTINF:6,\nhttp://${req.headers.host}/video/seg.ts\n`;
|
||||
const compressed = upstreamAcceptEncoding?.includes('gzip') === true;
|
||||
res.writeHead(200, {
|
||||
'content-type': 'application/vnd.apple.mpegurl',
|
||||
...(compressed ? { 'content-encoding': 'gzip' } : {}),
|
||||
});
|
||||
res.end(compressed ? gzipSync(body) : body);
|
||||
},
|
||||
async (proxyOrigin, upstreamOrigin) => {
|
||||
const response = await fetch(`${proxyOrigin}/video/list.m3u8`, {
|
||||
headers: { 'accept-encoding': 'gzip' },
|
||||
});
|
||||
const body = await response.text();
|
||||
assert.equal(upstreamAcceptEncoding, 'identity');
|
||||
assert.ok(body.includes(`${proxyOrigin}/video/seg.ts`));
|
||||
assert.ok(!body.includes(upstreamOrigin));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('proxy accepts only origin-form targets for its configured HTTP upstream', async () => {
|
||||
let upstreamHits = 0;
|
||||
await withProxy(
|
||||
|
||||
@@ -7,22 +7,23 @@ interface ClientRequestLifecycle {
|
||||
closed: boolean;
|
||||
}
|
||||
|
||||
const DROPPED_REQUEST_HEADERS = new Set([
|
||||
'accept-encoding',
|
||||
'connection',
|
||||
'keep-alive',
|
||||
'transfer-encoding',
|
||||
'content-length',
|
||||
]);
|
||||
|
||||
export function forwardableRequestHeaders(
|
||||
headers: http.IncomingHttpHeaders,
|
||||
): http.OutgoingHttpHeaders {
|
||||
const result: http.OutgoingHttpHeaders = {};
|
||||
for (const [name, value] of Object.entries(headers)) {
|
||||
if (
|
||||
value === undefined ||
|
||||
name.toLowerCase() === 'connection' ||
|
||||
name.toLowerCase() === 'keep-alive' ||
|
||||
name.toLowerCase() === 'transfer-encoding' ||
|
||||
name.toLowerCase() === 'content-length'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (value === undefined || DROPPED_REQUEST_HEADERS.has(name.toLowerCase())) continue;
|
||||
result[name] = value;
|
||||
}
|
||||
result['accept-encoding'] = 'identity';
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -75,7 +76,6 @@ function requestAttempt(
|
||||
};
|
||||
upstream.once('end', clearActiveRequest);
|
||||
upstream.once('close', clearActiveRequest);
|
||||
upstreamRequest.setTimeout(0);
|
||||
const status = upstream.statusCode ?? 502;
|
||||
if (status === 404 || status >= 500) {
|
||||
if (mayRetry) {
|
||||
|
||||
Reference in New Issue
Block a user