Files
myplayer-vue/proxy.js
2025-12-29 15:40:42 +08:00

114 lines
3.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import express from 'express';
import fetch from 'node-fetch';
import { URL } from 'url';
const app = express();
const port = 3000;
// 允许跨域请求
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Range');
next();
});
// 通用代理路由
app.get('/proxy', async (req, res) => {
console.log('Received Range header:', req.headers.range);
// 获取目标 URL
const targetUrl = req.query.url;
console.log('Fetching data from:', targetUrl);
if (!targetUrl) {
return res.status(400).json({ error: 'URL parameter is required' });
}
try {
// 设置请求头
const headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
};
if (req.headers.range) {
headers['Range'] = req.headers.range; // 转发 Range 请求头,支持视频分段加载
}
// 向目标 URL 发起请求
const response = await fetch(targetUrl, { headers });
// 检查响应状态
if (!response.ok) {
return res.status(response.status).json({
error: `Failed to fetch: ${response.statusText}`,
status: response.status
});
}
// 设置响应头
response.headers.forEach((value, key) => {
// 跳过一些可能导致问题的头信息
if (key.toLowerCase() !== 'content-encoding' &&
key.toLowerCase() !== 'transfer-encoding' &&
key.toLowerCase() !== 'connection') {
res.setHeader(key, value);
}
});
// 特殊处理 Transfer-Encoding 和 Content-Length
if (response.headers.get('transfer-encoding') === 'chunked') {
res.removeHeader('Content-Length');
}
// 将响应体直接流式传输给客户端
if (response.body) {
response.body.pipe(res, { end: true });
// 错误处理
response.body.on('error', (err) => {
console.error('Error during data transfer:', err);
if (!res.headersSent) {
res.status(500).json({ error: 'Error during data transfer' });
}
});
} else {
res.status(500).json({ error: 'No response body' });
}
} catch (error) {
console.error('Error fetching data:', error);
// 根据错误类型返回更具体的错误信息
let errorMessage = 'Error fetching data';
let statusCode = 500;
let hostname = '';
try {
hostname = new URL(targetUrl).hostname;
} catch (e) {
hostname = 'unknown';
}
if (error.code === 'ENOTFOUND') {
errorMessage = `DNS解析失败无法解析域名 "${hostname}"。请检查URL是否正确或网络连接是否正常。`;
statusCode = 502;
} else if (error.code === 'ECONNREFUSED') {
errorMessage = `连接被拒绝:无法连接到目标服务器 "${hostname}"。`;
statusCode = 502;
} else if (error.code === 'ETIMEDOUT') {
errorMessage = `请求超时:目标服务器 "${hostname}" 响应时间过长。`;
statusCode = 504;
}
if (!res.headersSent) {
res.status(statusCode).json({
error: errorMessage,
code: error.code,
targetUrl: targetUrl
});
}
}
});
app.listen(port, () => {
console.log(`Proxy server running at http://localhost:${port}`);
});