外部播放器使用代理m3u8时增加鉴权
This commit is contained in:
@@ -7,13 +7,25 @@ export const runtime = 'nodejs';
|
||||
/**
|
||||
* M3U8 代理接口
|
||||
* 用于外部播放器访问,会执行去广告逻辑并处理相对链接
|
||||
* GET /api/proxy-m3u8?url=<原始m3u8地址>&source=<播放源>
|
||||
* GET /api/proxy-m3u8?url=<原始m3u8地址>&source=<播放源>&token=<鉴权token>
|
||||
*/
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const m3u8Url = searchParams.get('url');
|
||||
const source = searchParams.get('source') || '';
|
||||
const token = searchParams.get('token');
|
||||
|
||||
// Token 鉴权:如果环境变量设置了 token,则必须验证
|
||||
const envToken = process.env.NEXT_PUBLIC_PROXY_M3U8_TOKEN;
|
||||
if (envToken && envToken.trim() !== '') {
|
||||
if (!token || token !== envToken) {
|
||||
return NextResponse.json(
|
||||
{ error: '无效的访问令牌' },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m3u8Url) {
|
||||
return NextResponse.json(
|
||||
@@ -70,7 +82,7 @@ export async function GET(request: Request) {
|
||||
}
|
||||
|
||||
// 处理 m3u8 中的相对链接
|
||||
m3u8Content = resolveM3u8Links(m3u8Content, m3u8Url, source, origin);
|
||||
m3u8Content = resolveM3u8Links(m3u8Content, m3u8Url, source, origin, token || '');
|
||||
|
||||
// 返回处理后的 m3u8 内容
|
||||
return new NextResponse(m3u8Content, {
|
||||
@@ -134,7 +146,7 @@ function filterAdsFromM3U8Default(type: string, m3u8Content: string): string {
|
||||
/**
|
||||
* 将 m3u8 中的相对链接转换为绝对链接,并将子 m3u8 链接转为代理链接
|
||||
*/
|
||||
function resolveM3u8Links(m3u8Content: string, baseUrl: string, source: string, proxyOrigin: string): string {
|
||||
function resolveM3u8Links(m3u8Content: string, baseUrl: string, source: string, proxyOrigin: string, token: string): string {
|
||||
const lines = m3u8Content.split('\n');
|
||||
const resolvedLines = [];
|
||||
|
||||
@@ -203,7 +215,8 @@ function resolveM3u8Links(m3u8Content: string, baseUrl: string, source: string,
|
||||
// 2. 检查是否是子 m3u8,如果是,转换为代理链接
|
||||
const isM3u8 = url.includes('.m3u8') || isNextLineUrl;
|
||||
if (isM3u8) {
|
||||
url = `${proxyOrigin}/api/proxy-m3u8?url=${encodeURIComponent(url)}${source ? `&source=${encodeURIComponent(source)}` : ''}`;
|
||||
const tokenParam = token ? `&token=${encodeURIComponent(token)}` : '';
|
||||
url = `${proxyOrigin}/api/proxy-m3u8?url=${encodeURIComponent(url)}${source ? `&source=${encodeURIComponent(source)}` : ''}${tokenParam}`;
|
||||
}
|
||||
|
||||
resolvedLines.push(url);
|
||||
|
||||
+17
-7
@@ -62,6 +62,9 @@ function PlayPageClient() {
|
||||
const searchParams = useSearchParams();
|
||||
const enableComments = useEnableComments();
|
||||
|
||||
// 获取 Proxy M3U8 Token
|
||||
const proxyToken = typeof window !== 'undefined' ? process.env.NEXT_PUBLIC_PROXY_M3U8_TOKEN || '' : '';
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 状态变量(State)
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -3420,8 +3423,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
const isM3u8 = videoUrl.toLowerCase().includes('.m3u8') || videoUrl.toLowerCase().includes('/m3u8/');
|
||||
|
||||
@@ -3479,8 +3483,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
// URL encode 避免冒号被吃掉
|
||||
window.open(`potplayer://${proxyUrl}`, '_blank');
|
||||
@@ -3503,8 +3508,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
// URL encode 避免冒号被吃掉
|
||||
window.open(`vlc://${proxyUrl}`, '_blank');
|
||||
@@ -3527,8 +3533,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
// URL encode 避免冒号被吃掉
|
||||
window.open(`mpv://${proxyUrl}`, '_blank');
|
||||
@@ -3551,8 +3558,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
window.open(
|
||||
`intent://${proxyUrl}#Intent;package=com.mxtech.videoplayer.ad;S.title=${encodeURIComponent(
|
||||
@@ -3579,8 +3587,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
window.open(`nplayer-${proxyUrl}`, '_blank');
|
||||
}}
|
||||
@@ -3602,8 +3611,9 @@ function PlayPageClient() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// 使用代理 URL
|
||||
const tokenParam = proxyToken ? `&token=${encodeURIComponent(proxyToken)}` : '';
|
||||
const proxyUrl = externalPlayerAdBlock
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}`
|
||||
? `${window.location.origin}/api/proxy-m3u8?url=${encodeURIComponent(videoUrl)}&source=${encodeURIComponent(currentSource)}${tokenParam}`
|
||||
: videoUrl;
|
||||
window.open(
|
||||
`iina://weblink?url=${encodeURIComponent(
|
||||
|
||||
Reference in New Issue
Block a user