Spaces:
Running
Running
fix: sanitize application proxy search parameters and improve connection lifecycle management for upstream requests
Browse files- health-server.js +21 -2
health-server.js
CHANGED
|
@@ -80,6 +80,14 @@ function mapAppProxyPath(path) {
|
|
| 80 |
return path;
|
| 81 |
}
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
function appendForwarded(existingValue, nextValue) {
|
| 84 |
const cleanNext = nextValue || "";
|
| 85 |
if (!existingValue) return cleanNext;
|
|
@@ -998,6 +1006,7 @@ async function createUptimeRobotMonitor(apiKey, host) {
|
|
| 998 |
|
| 999 |
function proxyHttp(req, res, proxyPath = req.url, proxyPort = GATEWAY_PORT) {
|
| 1000 |
const clientIp = getForwardedClientIp(req);
|
|
|
|
| 1001 |
const proxyReq = http.request(
|
| 1002 |
{
|
| 1003 |
hostname: GATEWAY_HOST,
|
|
@@ -1007,12 +1016,18 @@ function proxyHttp(req, res, proxyPath = req.url, proxyPort = GATEWAY_PORT) {
|
|
| 1007 |
headers: buildProxyHeaders(req.headers, clientIp),
|
| 1008 |
},
|
| 1009 |
(proxyRes) => {
|
|
|
|
| 1010 |
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers);
|
| 1011 |
proxyRes.pipe(res);
|
| 1012 |
},
|
| 1013 |
);
|
| 1014 |
|
| 1015 |
proxyReq.on("error", (error) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1016 |
res.writeHead(502, { "Content-Type": "application/json" });
|
| 1017 |
res.end(
|
| 1018 |
JSON.stringify({
|
|
@@ -1023,6 +1038,10 @@ function proxyHttp(req, res, proxyPath = req.url, proxyPort = GATEWAY_PORT) {
|
|
| 1023 |
);
|
| 1024 |
});
|
| 1025 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1026 |
req.pipe(proxyReq);
|
| 1027 |
}
|
| 1028 |
|
|
@@ -1225,7 +1244,7 @@ const server = http.createServer((req, res) => {
|
|
| 1225 |
}
|
| 1226 |
|
| 1227 |
if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
|
| 1228 |
-
const proxyPath = mapAppProxyPath(pathname) + (parsedUrl
|
| 1229 |
proxyHttp(req, res, proxyPath, GATEWAY_PORT);
|
| 1230 |
return;
|
| 1231 |
}
|
|
@@ -1242,7 +1261,7 @@ server.on("upgrade", (req, socket, head) => {
|
|
| 1242 |
|
| 1243 |
if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
|
| 1244 |
const parsedUrl = parseRequestUrl(req.url || "/");
|
| 1245 |
-
const proxyPath = mapAppProxyPath(pathname) + (parsedUrl
|
| 1246 |
proxyUpgrade(req, socket, head, proxyPath, GATEWAY_PORT);
|
| 1247 |
return;
|
| 1248 |
}
|
|
|
|
| 80 |
return path;
|
| 81 |
}
|
| 82 |
|
| 83 |
+
function sanitizeAppProxySearch(parsedUrl) {
|
| 84 |
+
const filtered = new URLSearchParams(parsedUrl.searchParams);
|
| 85 |
+
// HF Space UI sometimes appends its own control params to deep links.
|
| 86 |
+
filtered.delete("logs");
|
| 87 |
+
const query = filtered.toString();
|
| 88 |
+
return query ? `?${query}` : "";
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
function appendForwarded(existingValue, nextValue) {
|
| 92 |
const cleanNext = nextValue || "";
|
| 93 |
if (!existingValue) return cleanNext;
|
|
|
|
| 1006 |
|
| 1007 |
function proxyHttp(req, res, proxyPath = req.url, proxyPort = GATEWAY_PORT) {
|
| 1008 |
const clientIp = getForwardedClientIp(req);
|
| 1009 |
+
let upstreamStarted = false;
|
| 1010 |
const proxyReq = http.request(
|
| 1011 |
{
|
| 1012 |
hostname: GATEWAY_HOST,
|
|
|
|
| 1016 |
headers: buildProxyHeaders(req.headers, clientIp),
|
| 1017 |
},
|
| 1018 |
(proxyRes) => {
|
| 1019 |
+
upstreamStarted = true;
|
| 1020 |
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers);
|
| 1021 |
proxyRes.pipe(res);
|
| 1022 |
},
|
| 1023 |
);
|
| 1024 |
|
| 1025 |
proxyReq.on("error", (error) => {
|
| 1026 |
+
if (res.headersSent || upstreamStarted) {
|
| 1027 |
+
res.destroy();
|
| 1028 |
+
return;
|
| 1029 |
+
}
|
| 1030 |
+
|
| 1031 |
res.writeHead(502, { "Content-Type": "application/json" });
|
| 1032 |
res.end(
|
| 1033 |
JSON.stringify({
|
|
|
|
| 1038 |
);
|
| 1039 |
});
|
| 1040 |
|
| 1041 |
+
res.on("close", () => {
|
| 1042 |
+
proxyReq.destroy();
|
| 1043 |
+
});
|
| 1044 |
+
|
| 1045 |
req.pipe(proxyReq);
|
| 1046 |
}
|
| 1047 |
|
|
|
|
| 1244 |
}
|
| 1245 |
|
| 1246 |
if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
|
| 1247 |
+
const proxyPath = mapAppProxyPath(pathname) + sanitizeAppProxySearch(parsedUrl);
|
| 1248 |
proxyHttp(req, res, proxyPath, GATEWAY_PORT);
|
| 1249 |
return;
|
| 1250 |
}
|
|
|
|
| 1261 |
|
| 1262 |
if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
|
| 1263 |
const parsedUrl = parseRequestUrl(req.url || "/");
|
| 1264 |
+
const proxyPath = mapAppProxyPath(pathname) + sanitizeAppProxySearch(parsedUrl);
|
| 1265 |
proxyUpgrade(req, socket, head, proxyPath, GATEWAY_PORT);
|
| 1266 |
return;
|
| 1267 |
}
|