mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 08:46:40 +08:00
rollback service.js
This commit is contained in:
+9
-135
@@ -1,7 +1,6 @@
|
|||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const proxy = require('express-http-proxy')
|
const proxy = require('express-http-proxy')
|
||||||
const { createProxyMiddleware } = require('http-proxy-middleware')
|
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const port = process.env.NGINX_PORT || 3000
|
const port = process.env.NGINX_PORT || 3000
|
||||||
@@ -15,141 +14,16 @@ const proxyConfig = {
|
|||||||
// 静态文件服务目录
|
// 静态文件服务目录
|
||||||
app.use(express.static(__dirname))
|
app.use(express.static(__dirname))
|
||||||
|
|
||||||
// 创建专门的SSE代理中间件
|
// 配置代理中间件将请求转发给后端API
|
||||||
const sseProxyMiddleware = createProxyMiddleware({
|
app.use(
|
||||||
target: `http://${proxyConfig.URL}:${proxyConfig.PORT}`,
|
'/api',
|
||||||
changeOrigin: true,
|
proxy(`${proxyConfig.URL}:${proxyConfig.PORT}`, {
|
||||||
ws: false,
|
// 路径加上 /api 前缀
|
||||||
timeout: 0, // 无超时
|
proxyReqPathResolver: (req) => {
|
||||||
proxyTimeout: 0, // 无超时
|
return `/api${req.url}`
|
||||||
headers: {
|
|
||||||
'Connection': 'keep-alive',
|
|
||||||
'Cache-Control': 'no-cache'
|
|
||||||
},
|
|
||||||
onProxyRes: (proxyRes, req, res) => {
|
|
||||||
// 检测SSE响应
|
|
||||||
const isSSE = proxyRes.headers['content-type'] &&
|
|
||||||
proxyRes.headers['content-type'].includes('text/event-stream');
|
|
||||||
|
|
||||||
if (isSSE) {
|
|
||||||
// 设置SSE响应头
|
|
||||||
res.writeHead(proxyRes.statusCode, {
|
|
||||||
'Content-Type': 'text/event-stream',
|
|
||||||
'Cache-Control': 'no-cache',
|
|
||||||
'Connection': 'keep-alive',
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Allow-Headers': 'Cache-Control, Content-Type, Authorization'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 直接将代理响应流式传输到客户端
|
|
||||||
proxyRes.pipe(res);
|
|
||||||
|
|
||||||
// 处理客户端断开连接
|
|
||||||
req.on('close', () => {
|
|
||||||
console.log('Client disconnected from SSE stream');
|
|
||||||
if (proxyRes.destroy) {
|
|
||||||
proxyRes.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理代理响应结束
|
|
||||||
proxyRes.on('end', () => {
|
|
||||||
console.log('SSE stream ended');
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理代理响应错误
|
|
||||||
proxyRes.on('error', (err) => {
|
|
||||||
console.error('SSE proxy response error:', err);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(500).end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
onError: (err, req, res) => {
|
);
|
||||||
console.error('SSE proxy error:', err);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(500).json({ error: 'Proxy error' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 创建普通API代理中间件
|
|
||||||
const apiProxyMiddleware = proxy(`${proxyConfig.URL}:${proxyConfig.PORT}`, {
|
|
||||||
// 路径加上 /api 前缀
|
|
||||||
proxyReqPathResolver: (req) => {
|
|
||||||
return `/api${req.url}`
|
|
||||||
},
|
|
||||||
proxyReqOptDecorator: (proxyReqOpts, srcReq) => {
|
|
||||||
proxyReqOpts.headers = proxyReqOpts.headers || {};
|
|
||||||
|
|
||||||
// 检测是否为SSE请求
|
|
||||||
const isSSE = srcReq.headers.accept && srcReq.headers.accept.includes('text/event-stream');
|
|
||||||
|
|
||||||
if (!isSSE) {
|
|
||||||
// 普通请求设置超时
|
|
||||||
proxyReqOpts.timeout = 600000; // 600秒超时
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxyReqOpts;
|
|
||||||
},
|
|
||||||
userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
|
|
||||||
// 只处理非SSE响应
|
|
||||||
const isSSEResponse = proxyRes.headers['content-type'] &&
|
|
||||||
proxyRes.headers['content-type'].includes('text/event-stream');
|
|
||||||
|
|
||||||
if (!isSSEResponse) {
|
|
||||||
// 普通响应:正常处理
|
|
||||||
return proxyResData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSE响应不在这里处理,已经由专门的中间件处理
|
|
||||||
return proxyResData;
|
|
||||||
},
|
|
||||||
// 错误处理
|
|
||||||
proxyErrorHandler: (err, res, next) => {
|
|
||||||
// 客户端断开连接的正常情况
|
|
||||||
if (err.code === 'ECONNRESET' || err.code === 'EPIPE') {
|
|
||||||
console.log('Client disconnected:', err.code);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时错误处理
|
|
||||||
if (err.code === 'ETIMEDOUT') {
|
|
||||||
console.log('Proxy request timed out:', err.code);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(504).send('Gateway Timeout');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他错误
|
|
||||||
console.error('Proxy error:', err);
|
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(500).send('Internal Server Error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 配置API代理路由
|
|
||||||
app.use('/api', (req, res, next) => {
|
|
||||||
// 检测是否为SSE请求
|
|
||||||
const isSSE = req.headers.accept && req.headers.accept.includes('text/event-stream');
|
|
||||||
|
|
||||||
if (isSSE) {
|
|
||||||
// 使用专门的SSE代理中间件
|
|
||||||
sseProxyMiddleware(req, res, next);
|
|
||||||
} else {
|
|
||||||
// 使用普通API代理中间件
|
|
||||||
apiProxyMiddleware(req, res, next);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 配置代理中间件将CookieCloud请求转发给后端API
|
// 配置代理中间件将CookieCloud请求转发给后端API
|
||||||
app.use(
|
app.use(
|
||||||
|
|||||||
Reference in New Issue
Block a user