mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-06 08:58:05 +00:00
fix(proxy): re-stream express.json()-consumed body to remote nodes for POST/PUT/PATCH
express.json() fully drains the incoming request stream. http-proxy-middleware then pipes an already-consumed empty stream to the remote Sencho instance, which holds the connection open waiting for body bytes that never arrive (Content-Length says N but 0 bytes are forwarded). This caused all POST/PUT/PATCH requests to remote nodes — most visibly 'Add Alert Rule' — to hang indefinitely with an infinite loading spinner. Fix: in the proxyReq handler, write JSON.stringify(req.body) with correct Content-Type and Content-Length headers before forwarding, restoring the full request body.
This commit is contained in:
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Fixed:** `SettingsModal` Notifications tab is no longer hidden when a remote node is active — users can now configure Discord/Slack/Webhook channels directly on any remote node. The section header shows the remote node name and a "Remote" badge with a tooltip explaining that channels are saved on the remote instance.
|
||||
- **Fixed:** `StackAlertSheet` form error handling now surfaces the actual server error message (`err.error`) instead of a generic "Failed to add alert rule." string; console error logging added for all failure paths to aid debugging.
|
||||
- **Fixed:** `POST /api/alerts` now validates the request body with a Zod schema — rejects unknown metric/operator values, negative thresholds, and missing required fields with a structured 400 response instead of passing raw input to SQLite.
|
||||
- **Fixed:** Remote node HTTP proxy (`remoteNodeProxy` in `index.ts`) now re-streams the parsed request body for POST/PUT/PATCH requests — `express.json()` drains the incoming stream into `req.body`, leaving the raw stream empty; the proxy then forwarded a request with a `Content-Length` header but zero body bytes, causing the remote Express server to stall waiting for the body indefinitely (the "Add Rule spins forever" bug on remote nodes). The `proxyReq` handler now writes `JSON.stringify(req.body)` with correct `Content-Type` and `Content-Length` headers before forwarding.
|
||||
- **Fixed:** WebSocket notification reconnect in `EditorLayout` upgraded to exponential backoff (1 s → 2 s → 4 s → 8 s → 16 s → 30 s max) instead of a flat 5-second retry; `ws.onerror` now logs the event rather than silently calling `close()`; cleanup correctly guards against closing a WebSocket that is already in CLOSING/CLOSED state, eliminating the "WebSocket is closed before the connection is established" console error on React StrictMode double-mount.
|
||||
- **Security:** Host Console and container exec WebSocket endpoints now reject `node_proxy` scoped JWT tokens with HTTP 403 — machine-to-machine proxy credentials can no longer be used to open interactive terminals.
|
||||
- **Security:** `stackParam` query parameter on `/api/system/host-console` is now validated against `path.resolve` + `startsWith(baseDir)` to prevent directory traversal when setting the PTY working directory.
|
||||
|
||||
@@ -370,6 +370,18 @@ const remoteNodeProxy = createProxyMiddleware<Request, Response>({
|
||||
const newQs = params.toString();
|
||||
proxyReq.path = pathname + (newQs ? `?${newQs}` : '');
|
||||
}
|
||||
// Re-stream the request body for POST/PUT/PATCH requests.
|
||||
// express.json() fully drains the incoming stream and stores the parsed
|
||||
// object in req.body. http-proxy-middleware then pipes an already-consumed
|
||||
// stream to the remote, which causes the remote server to stall waiting for
|
||||
// body bytes that never arrive (the Content-Length header says N bytes but
|
||||
// 0 are forwarded), hanging the request indefinitely.
|
||||
if (req.body && Object.keys(req.body).length > 0) {
|
||||
const bodyData = JSON.stringify(req.body);
|
||||
proxyReq.setHeader('Content-Type', 'application/json');
|
||||
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
|
||||
proxyReq.write(bodyData);
|
||||
}
|
||||
},
|
||||
error: (err, _req, proxyRes) => {
|
||||
console.error('[Proxy] Remote node error:', (err as Error).message);
|
||||
|
||||
Reference in New Issue
Block a user