0.3.2.1 UI修复3
This commit is contained in:
@@ -19,6 +19,7 @@ const next = require("next");
|
||||
const { parse: parseUrl } = require("url");
|
||||
|
||||
const ONLYOFFICE_PREFIX = "/onlyoffice-server";
|
||||
const CONVEX_PREFIX = "/convex";
|
||||
|
||||
function readArgValue(flag) {
|
||||
const idx = process.argv.findIndex((x) => x === flag);
|
||||
@@ -48,10 +49,19 @@ function isOnlyOfficePath(urlString) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildUpstreamRequestHead(req, targetUrl) {
|
||||
function isConvexPath(urlString) {
|
||||
try {
|
||||
const u = new URL(urlString, "http://localhost");
|
||||
return u.pathname === CONVEX_PREFIX || u.pathname.startsWith(`${CONVEX_PREFIX}/`);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildUpstreamRequestHead(req, targetUrl, prefix) {
|
||||
const incoming = new URL(req.url || "/", "http://localhost");
|
||||
const rawPath = incoming.pathname || "/";
|
||||
const stripped = rawPath === ONLYOFFICE_PREFIX ? "/" : rawPath.slice(ONLYOFFICE_PREFIX.length) || "/";
|
||||
const stripped = rawPath === prefix ? "/" : rawPath.slice(prefix.length) || "/";
|
||||
|
||||
const basePath = String(targetUrl.pathname || "/").replace(/\/+$/, "") || "";
|
||||
const upstreamPath = `${basePath}${stripped}`.replace(/\/{2,}/g, "/") + (incoming.search || "");
|
||||
@@ -108,7 +118,7 @@ function buildUpstreamRequestHead(req, targetUrl) {
|
||||
lines.push(`x-forwarded-host: ${forwardedHost}`);
|
||||
lines.push(`x-forwarded-proto: ${forwardedProto}`);
|
||||
lines.push(`x-forwarded-port: ${forwardedPort}`);
|
||||
lines.push(`x-forwarded-prefix: ${ONLYOFFICE_PREFIX}`);
|
||||
lines.push(`x-forwarded-prefix: ${prefix}`);
|
||||
|
||||
// 说明:Host 必须指向 ONLYOFFICE_INTERNAL_URL,否则上游可能拒绝 Upgrade。
|
||||
lines.push(`Host: ${targetUrl.host}`);
|
||||
@@ -123,7 +133,7 @@ function proxyOnlyOfficeUpgrade(req, socket, head) {
|
||||
|
||||
const upstream = net.connect({ host: target.hostname, port }, () => {
|
||||
try {
|
||||
const reqHead = buildUpstreamRequestHead(req, target);
|
||||
const reqHead = buildUpstreamRequestHead(req, target, ONLYOFFICE_PREFIX);
|
||||
upstream.write(reqHead);
|
||||
if (head && head.length > 0) upstream.write(head);
|
||||
socket.pipe(upstream);
|
||||
@@ -156,6 +166,116 @@ function proxyOnlyOfficeUpgrade(req, socket, head) {
|
||||
socket.on("error", onError);
|
||||
}
|
||||
|
||||
function resolveConvexInternalUrl() {
|
||||
// 说明:Convex 本地 dev server 默认 3210;对外访问(如 frp https)时,浏览器需要 wss,
|
||||
// 因此这里通过同源反代把 Upgrade 转发到本机 3210。
|
||||
const raw = (process.env.CONVEX_INTERNAL_URL || "http://127.0.0.1:3210").trim();
|
||||
try {
|
||||
return new URL(raw.replace(/\/+$/, "") + "/");
|
||||
} catch {
|
||||
return new URL("http://127.0.0.1:3210/");
|
||||
}
|
||||
}
|
||||
|
||||
function proxyConvexUpgrade(req, socket, head) {
|
||||
const target = resolveConvexInternalUrl();
|
||||
const port = Number(target.port) || (target.protocol === "https:" ? 443 : 80);
|
||||
|
||||
const upstream = net.connect({ host: target.hostname, port }, () => {
|
||||
try {
|
||||
const reqHead = buildUpstreamRequestHead(req, target, CONVEX_PREFIX);
|
||||
upstream.write(reqHead);
|
||||
if (head && head.length > 0) upstream.write(head);
|
||||
socket.pipe(upstream);
|
||||
upstream.pipe(socket);
|
||||
} catch {
|
||||
try {
|
||||
socket.destroy();
|
||||
} catch {}
|
||||
try {
|
||||
upstream.destroy();
|
||||
} catch {}
|
||||
}
|
||||
});
|
||||
|
||||
const onError = (err) => {
|
||||
try {
|
||||
const msg = err && err.message ? String(err.message) : String(err || "");
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("[dev-server][convex-ws] proxy error", msg);
|
||||
} catch {}
|
||||
try {
|
||||
socket.destroy();
|
||||
} catch {}
|
||||
try {
|
||||
upstream.destroy();
|
||||
} catch {}
|
||||
};
|
||||
|
||||
upstream.on("error", onError);
|
||||
socket.on("error", onError);
|
||||
}
|
||||
|
||||
function proxyConvexHttp(req, res) {
|
||||
const target = resolveConvexInternalUrl();
|
||||
const incoming = new URL(req.url || "/", "http://localhost");
|
||||
const rawPath = incoming.pathname || "/";
|
||||
const stripped = rawPath === CONVEX_PREFIX ? "/" : rawPath.slice(CONVEX_PREFIX.length) || "/";
|
||||
const upstreamPath = stripped + (incoming.search || "");
|
||||
|
||||
const isHttps = target.protocol === "https:";
|
||||
const mod = isHttps ? require("https") : require("http");
|
||||
|
||||
const headers = { ...(req.headers || {}) };
|
||||
headers.host = target.host;
|
||||
// 说明:让上游能感知对外协议/域名(主要用于调试;Convex 本身通常不依赖这些头)。
|
||||
const forwardedHostRaw = String(headers["x-forwarded-host"] || req.headers.host || "");
|
||||
const forwardedHost = forwardedHostRaw.split(",")[0].trim() || "localhost";
|
||||
const forwardedProto =
|
||||
String(headers["x-forwarded-proto"] || "").split(",")[0].trim() ||
|
||||
(String(req.headers.origin || "").startsWith("https") ? "https" : "http");
|
||||
const forwardedPortRaw = String(headers["x-forwarded-port"] || "").split(",")[0].trim();
|
||||
const forwardedPort = (() => {
|
||||
if (forwardedPortRaw) return forwardedPortRaw;
|
||||
const hostHasPort = forwardedHost.includes(":") ? forwardedHost.split(":").pop() : "";
|
||||
if (hostHasPort && /^\d+$/.test(hostHasPort)) return hostHasPort;
|
||||
return forwardedProto === "https" ? "443" : "80";
|
||||
})();
|
||||
|
||||
headers["x-forwarded-host"] = forwardedHost;
|
||||
headers["x-forwarded-proto"] = forwardedProto;
|
||||
headers["x-forwarded-port"] = forwardedPort;
|
||||
headers["x-forwarded-prefix"] = CONVEX_PREFIX;
|
||||
|
||||
const upstreamReq = mod.request(
|
||||
{
|
||||
protocol: target.protocol,
|
||||
hostname: target.hostname,
|
||||
port: target.port || (isHttps ? 443 : 80),
|
||||
method: req.method,
|
||||
path: upstreamPath,
|
||||
headers,
|
||||
},
|
||||
(upstreamRes) => {
|
||||
res.writeHead(upstreamRes.statusCode || 502, upstreamRes.headers || {});
|
||||
upstreamRes.pipe(res);
|
||||
},
|
||||
);
|
||||
|
||||
upstreamReq.on("error", (err) => {
|
||||
try {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("[dev-server][convex-http] proxy error", err && err.message ? err.message : String(err || ""));
|
||||
} catch {}
|
||||
try {
|
||||
res.statusCode = 502;
|
||||
res.end("Bad Gateway");
|
||||
} catch {}
|
||||
});
|
||||
|
||||
req.pipe(upstreamReq);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const port = resolvePort();
|
||||
const hostname = resolveHostname();
|
||||
@@ -172,14 +292,38 @@ async function main() {
|
||||
try {
|
||||
res.setHeader("x-mnote-dev-server", "1");
|
||||
res.setHeader("x-mnote-onlyoffice-ws-proxy", "1");
|
||||
res.setHeader("x-mnote-convex-ws-proxy", "1");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (isConvexPath(req.url || "/")) {
|
||||
proxyConvexHttp(req, res);
|
||||
return;
|
||||
}
|
||||
|
||||
const parsed = parseUrl(req.url || "/", true);
|
||||
handle(req, res, parsed);
|
||||
});
|
||||
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
if (isConvexPath(req.url || "/")) {
|
||||
try {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
"[dev-server][convex-ws] upgrade",
|
||||
req.url,
|
||||
"host=",
|
||||
req.headers.host,
|
||||
"xfp=",
|
||||
req.headers["x-forwarded-proto"],
|
||||
"xfh=",
|
||||
req.headers["x-forwarded-host"],
|
||||
);
|
||||
} catch {}
|
||||
proxyConvexUpgrade(req, socket, head);
|
||||
return;
|
||||
}
|
||||
if (isOnlyOfficePath(req.url || "/")) {
|
||||
try {
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -210,7 +354,9 @@ async function main() {
|
||||
|
||||
server.listen(port, hostname, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[dev-server] ready http://${hostname}:${port} (ONLYOFFICE ws via ${ONLYOFFICE_PREFIX} -> ${process.env.ONLYOFFICE_INTERNAL_URL || "http://127.0.0.1:8081"})`);
|
||||
console.log(
|
||||
`[dev-server] ready http://${hostname}:${port} (ONLYOFFICE ws via ${ONLYOFFICE_PREFIX} -> ${process.env.ONLYOFFICE_INTERNAL_URL || "http://127.0.0.1:8081"}; Convex ws via ${CONVEX_PREFIX} -> ${process.env.CONVEX_INTERNAL_URL || "http://127.0.0.1:3210"})`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user