somratpro commited on
Commit
f6ab881
·
1 Parent(s): 06ae20d

feat: namespace dashboard routes under /dashboard and add proxy support for app sub-routes

Browse files
Files changed (1) hide show
  1. health-server.js +50 -11
health-server.js CHANGED
@@ -12,6 +12,11 @@ const LLM_MODEL = process.env.LLM_MODEL || "Not Set";
12
  const TELEGRAM_ENABLED = !!process.env.TELEGRAM_BOT_TOKEN;
13
  const WHATSAPP_ENABLED = /^true$/i.test(process.env.WHATSAPP_ENABLED || "");
14
  const WHATSAPP_STATUS_FILE = "/tmp/huggingclaw-wa-status.json";
 
 
 
 
 
15
 
16
  function parseRequestUrl(url) {
17
  try {
@@ -22,7 +27,15 @@ function parseRequestUrl(url) {
22
  }
23
 
24
  function isDashboardRoute(pathname) {
25
- return pathname === "/dashboard" || pathname === "/dashboard/";
 
 
 
 
 
 
 
 
26
  }
27
 
28
  function isLocalRoute(pathname) {
@@ -30,10 +43,21 @@ function isLocalRoute(pathname) {
30
  pathname === "/health" ||
31
  pathname === "/status" ||
32
  pathname === "/uptimerobot/setup" ||
 
 
 
33
  isDashboardRoute(pathname)
34
  );
35
  }
36
 
 
 
 
 
 
 
 
 
37
  function appendForwarded(existingValue, nextValue) {
38
  const cleanNext = nextValue || "";
39
  if (!existingValue) return cleanNext;
@@ -454,7 +478,7 @@ function renderDashboard() {
454
  <span class="stat-label">Telegram</span>
455
  <span id="tg-status">Loading...</span>
456
  </div>
457
- <a href="/" class="stat-btn">Open Control UI</a>
458
  </div>
459
 
460
  <div class="stat-card" style="width: 100%;">
@@ -510,7 +534,7 @@ function renderDashboard() {
510
  <script>
511
  async function updateStats() {
512
  try {
513
- const res = await fetch('/status');
514
  const data = await res.json();
515
 
516
  document.getElementById('model-id').textContent = data.model;
@@ -600,7 +624,7 @@ function renderDashboard() {
600
  result.textContent = '';
601
 
602
  try {
603
- const res = await fetch('/uptimerobot/setup', {
604
  method: 'POST',
605
  headers: { 'Content-Type': 'application/json' },
606
  body: JSON.stringify({ apiKey })
@@ -745,13 +769,13 @@ async function createUptimeRobotMonitor(apiKey, host) {
745
  };
746
  }
747
 
748
- function proxyHttp(req, res) {
749
  const proxyReq = http.request(
750
  {
751
  hostname: GATEWAY_HOST,
752
  port: GATEWAY_PORT,
753
  method: req.method,
754
- path: req.url,
755
  headers: buildProxyHeaders(req.headers, req.socket.remoteAddress),
756
  },
757
  (proxyRes) => {
@@ -806,12 +830,12 @@ function serializeUpgradeHeaders(req, remoteAddress) {
806
  return forwardedHeaders;
807
  }
808
 
809
- function proxyUpgrade(req, socket, head) {
810
  const proxySocket = net.connect(GATEWAY_PORT, GATEWAY_HOST);
811
 
812
  proxySocket.on("connect", () => {
813
  const requestLines = [
814
- `${req.method} ${req.url} HTTP/${req.httpVersion}`,
815
  ...serializeUpgradeHeaders(req, req.socket.remoteAddress),
816
  "",
817
  "",
@@ -844,7 +868,7 @@ const server = http.createServer((req, res) => {
844
  const uptime = Math.floor((Date.now() - startTime) / 1000);
845
  const uptimeHuman = `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m`;
846
 
847
- if (pathname === "/health") {
848
  res.writeHead(200, { "Content-Type": "application/json" });
849
  res.end(
850
  JSON.stringify({
@@ -857,7 +881,7 @@ const server = http.createServer((req, res) => {
857
  return;
858
  }
859
 
860
- if (pathname === "/status") {
861
  void (async () => {
862
  const guardianStatus = readGuardianStatus();
863
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -878,7 +902,7 @@ const server = http.createServer((req, res) => {
878
  return;
879
  }
880
 
881
- if (pathname === "/uptimerobot/setup") {
882
  if (req.method !== "POST") {
883
  res.writeHead(405, { "Content-Type": "application/json" });
884
  res.end(JSON.stringify({ message: "Method not allowed" }));
@@ -925,6 +949,13 @@ const server = http.createServer((req, res) => {
925
  return;
926
  }
927
 
 
 
 
 
 
 
 
928
  proxyHttp(req, res);
929
  });
930
 
@@ -935,6 +966,14 @@ server.on("upgrade", (req, socket, head) => {
935
  return;
936
  }
937
 
 
 
 
 
 
 
 
 
938
  proxyUpgrade(req, socket, head);
939
  });
940
 
 
12
  const TELEGRAM_ENABLED = !!process.env.TELEGRAM_BOT_TOKEN;
13
  const WHATSAPP_ENABLED = /^true$/i.test(process.env.WHATSAPP_ENABLED || "");
14
  const WHATSAPP_STATUS_FILE = "/tmp/huggingclaw-wa-status.json";
15
+ const DASHBOARD_BASE = "/dashboard";
16
+ const DASHBOARD_STATUS_PATH = `${DASHBOARD_BASE}/status`;
17
+ const DASHBOARD_HEALTH_PATH = `${DASHBOARD_BASE}/health`;
18
+ const DASHBOARD_UPTIMEROBOT_PATH = `${DASHBOARD_BASE}/uptimerobot/setup`;
19
+ const DASHBOARD_APP_BASE = `${DASHBOARD_BASE}/app`;
20
 
21
  function parseRequestUrl(url) {
22
  try {
 
27
  }
28
 
29
  function isDashboardRoute(pathname) {
30
+ return pathname === DASHBOARD_BASE || pathname === `${DASHBOARD_BASE}/`;
31
+ }
32
+
33
+ function isDashboardScopedPath(pathname, suffix) {
34
+ return pathname === `${DASHBOARD_BASE}/${suffix}`;
35
+ }
36
+
37
+ function isDashboardAppRoute(pathname) {
38
+ return pathname === DASHBOARD_APP_BASE || pathname.startsWith(`${DASHBOARD_APP_BASE}/`);
39
  }
40
 
41
  function isLocalRoute(pathname) {
 
43
  pathname === "/health" ||
44
  pathname === "/status" ||
45
  pathname === "/uptimerobot/setup" ||
46
+ pathname === DASHBOARD_HEALTH_PATH ||
47
+ pathname === DASHBOARD_STATUS_PATH ||
48
+ pathname === DASHBOARD_UPTIMEROBOT_PATH ||
49
  isDashboardRoute(pathname)
50
  );
51
  }
52
 
53
+ function stripDashboardAppPrefix(path) {
54
+ if (path === DASHBOARD_APP_BASE) return "/";
55
+ if (path.startsWith(`${DASHBOARD_APP_BASE}/`)) {
56
+ return path.slice(DASHBOARD_APP_BASE.length) || "/";
57
+ }
58
+ return path;
59
+ }
60
+
61
  function appendForwarded(existingValue, nextValue) {
62
  const cleanNext = nextValue || "";
63
  if (!existingValue) return cleanNext;
 
478
  <span class="stat-label">Telegram</span>
479
  <span id="tg-status">Loading...</span>
480
  </div>
481
+ <a href="${DASHBOARD_APP_BASE}/" class="stat-btn">Open Control UI</a>
482
  </div>
483
 
484
  <div class="stat-card" style="width: 100%;">
 
534
  <script>
535
  async function updateStats() {
536
  try {
537
+ const res = await fetch('${DASHBOARD_STATUS_PATH}');
538
  const data = await res.json();
539
 
540
  document.getElementById('model-id').textContent = data.model;
 
624
  result.textContent = '';
625
 
626
  try {
627
+ const res = await fetch('${DASHBOARD_UPTIMEROBOT_PATH}', {
628
  method: 'POST',
629
  headers: { 'Content-Type': 'application/json' },
630
  body: JSON.stringify({ apiKey })
 
769
  };
770
  }
771
 
772
+ function proxyHttp(req, res, proxyPath = req.url) {
773
  const proxyReq = http.request(
774
  {
775
  hostname: GATEWAY_HOST,
776
  port: GATEWAY_PORT,
777
  method: req.method,
778
+ path: proxyPath,
779
  headers: buildProxyHeaders(req.headers, req.socket.remoteAddress),
780
  },
781
  (proxyRes) => {
 
830
  return forwardedHeaders;
831
  }
832
 
833
+ function proxyUpgrade(req, socket, head, proxyPath = req.url) {
834
  const proxySocket = net.connect(GATEWAY_PORT, GATEWAY_HOST);
835
 
836
  proxySocket.on("connect", () => {
837
  const requestLines = [
838
+ `${req.method} ${proxyPath} HTTP/${req.httpVersion}`,
839
  ...serializeUpgradeHeaders(req, req.socket.remoteAddress),
840
  "",
841
  "",
 
868
  const uptime = Math.floor((Date.now() - startTime) / 1000);
869
  const uptimeHuman = `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m`;
870
 
871
+ if (pathname === "/health" || pathname === DASHBOARD_HEALTH_PATH) {
872
  res.writeHead(200, { "Content-Type": "application/json" });
873
  res.end(
874
  JSON.stringify({
 
881
  return;
882
  }
883
 
884
+ if (pathname === "/status" || pathname === DASHBOARD_STATUS_PATH) {
885
  void (async () => {
886
  const guardianStatus = readGuardianStatus();
887
  res.writeHead(200, { "Content-Type": "application/json" });
 
902
  return;
903
  }
904
 
905
+ if (pathname === "/uptimerobot/setup" || pathname === DASHBOARD_UPTIMEROBOT_PATH) {
906
  if (req.method !== "POST") {
907
  res.writeHead(405, { "Content-Type": "application/json" });
908
  res.end(JSON.stringify({ message: "Method not allowed" }));
 
949
  return;
950
  }
951
 
952
+ if (isDashboardAppRoute(pathname)) {
953
+ const proxyPath =
954
+ stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
955
+ proxyHttp(req, res, proxyPath);
956
+ return;
957
+ }
958
+
959
  proxyHttp(req, res);
960
  });
961
 
 
966
  return;
967
  }
968
 
969
+ if (isDashboardAppRoute(pathname)) {
970
+ const parsedUrl = parseRequestUrl(req.url || "/");
971
+ const proxyPath =
972
+ stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
973
+ proxyUpgrade(req, socket, head, proxyPath);
974
+ return;
975
+ }
976
+
977
  proxyUpgrade(req, socket, head);
978
  });
979