网盘代理内存泄漏优化

This commit is contained in:
mtvpls
2026-04-26 21:29:22 +08:00
parent 1ccfb9cdce
commit a769642924
2 changed files with 149 additions and 51 deletions
+75 -26
View File
@@ -33,34 +33,83 @@ export async function GET(request: NextRequest) {
const { url, headers } = await getBaiduDirectPlayUrl(session.meta, file.fid, cookie);
const range = request.headers.get('range');
const upstream = await fetch(url, {
headers: {
...headers,
Cookie: cookie,
...(range ? { Range: range } : {}),
},
cache: 'no-store',
});
const abortController = new AbortController();
const timeoutId = setTimeout(() => abortController.abort(), 300000);
if (!upstream.ok || !upstream.body) {
return NextResponse.json(
{ error: `百度网盘视频代理失败 (${upstream.status})` },
{ status: upstream.status || 500 }
);
try {
const upstream = await fetch(url, {
headers: {
...headers,
Cookie: cookie,
...(range ? { Range: range } : {}),
},
cache: 'no-store',
signal: abortController.signal,
});
clearTimeout(timeoutId);
if (!upstream.ok || !upstream.body) {
return NextResponse.json(
{ error: `百度网盘视频代理失败 (${upstream.status})` },
{ status: upstream.status || 500 }
);
}
const responseHeaders = new Headers();
const copyHeaders = ['content-type', 'content-length', 'content-range', 'accept-ranges', 'etag', 'last-modified'];
copyHeaders.forEach((name) => {
const value = upstream.headers.get(name);
if (value) responseHeaders.set(name, value);
});
responseHeaders.set('Cache-Control', 'private, no-store');
const { readable, writable } = new TransformStream();
const reader = upstream.body.getReader();
void (async () => {
const writer = writable.getWriter();
try {
let streamDone = false;
while (!streamDone) {
const { done, value } = await reader.read();
if (done) {
streamDone = true;
} else {
await writer.write(value);
}
}
} catch {
try {
await reader.cancel();
} catch {
void 0;
}
} finally {
try {
reader.releaseLock();
} catch {
void 0;
}
try {
await writer.close();
} catch {
void 0;
}
}
})();
return new Response(readable, {
status: range && upstream.headers.get('content-range') ? 206 : upstream.status,
headers: responseHeaders,
});
} catch (error) {
clearTimeout(timeoutId);
if (error instanceof Error && error.name === 'AbortError') {
return NextResponse.json({ error: '百度网盘代理超时' }, { status: 504 });
}
throw error;
}
const responseHeaders = new Headers();
const copyHeaders = ['content-type', 'content-length', 'content-range', 'accept-ranges', 'etag', 'last-modified'];
copyHeaders.forEach((name) => {
const value = upstream.headers.get(name);
if (value) responseHeaders.set(name, value);
});
responseHeaders.set('Cache-Control', 'private, no-store');
return new Response(upstream.body, {
status: range && upstream.headers.get('content-range') ? 206 : 200,
headers: responseHeaders,
});
} catch (error) {
return NextResponse.json(
{ error: error instanceof Error ? error.message : '百度网盘代理失败' },
+74 -25
View File
@@ -59,33 +59,82 @@ export async function GET(request: NextRequest) {
}
const range = request.headers.get('range');
const upstream = await fetch(selected.url, {
headers: {
...getQuarkPlayHeaders(cookie),
...(range ? { Range: range } : {}),
},
cache: 'no-store',
});
const abortController = new AbortController();
const timeoutId = setTimeout(() => abortController.abort(), 300000);
if (!upstream.ok || !upstream.body) {
return NextResponse.json(
{ error: `夸克视频代理失败 (${upstream.status})` },
{ status: upstream.status || 500 }
);
try {
const upstream = await fetch(selected.url, {
headers: {
...getQuarkPlayHeaders(cookie),
...(range ? { Range: range } : {}),
},
cache: 'no-store',
signal: abortController.signal,
});
clearTimeout(timeoutId);
if (!upstream.ok || !upstream.body) {
return NextResponse.json(
{ error: `夸克视频代理失败 (${upstream.status})` },
{ status: upstream.status || 500 }
);
}
const responseHeaders = new Headers();
const copyHeaders = ['content-type', 'content-length', 'content-range', 'accept-ranges', 'etag', 'last-modified'];
copyHeaders.forEach((name) => {
const value = upstream.headers.get(name);
if (value) responseHeaders.set(name, value);
});
responseHeaders.set('Cache-Control', 'private, no-store');
const { readable, writable } = new TransformStream();
const reader = upstream.body.getReader();
void (async () => {
const writer = writable.getWriter();
try {
let streamDone = false;
while (!streamDone) {
const { done, value } = await reader.read();
if (done) {
streamDone = true;
} else {
await writer.write(value);
}
}
} catch {
try {
await reader.cancel();
} catch {
void 0;
}
} finally {
try {
reader.releaseLock();
} catch {
void 0;
}
try {
await writer.close();
} catch {
void 0;
}
}
})();
return new Response(readable, {
status: range && upstream.headers.get('content-range') ? 206 : upstream.status,
headers: responseHeaders,
});
} catch (error) {
clearTimeout(timeoutId);
if (error instanceof Error && error.name === 'AbortError') {
return NextResponse.json({ error: '夸克网盘代理超时' }, { status: 504 });
}
throw error;
}
const responseHeaders = new Headers();
const copyHeaders = ['content-type', 'content-length', 'content-range', 'accept-ranges', 'etag', 'last-modified'];
copyHeaders.forEach((name) => {
const value = upstream.headers.get(name);
if (value) responseHeaders.set(name, value);
});
responseHeaders.set('Cache-Control', 'private, no-store');
return new Response(upstream.body, {
status: range && upstream.headers.get('content-range') ? 206 : 200,
headers: responseHeaders,
});
} catch (error) {
return NextResponse.json(
{ error: error instanceof Error ? error.message : '夸克网盘代理失败' },