fix(t-1.0): fix broken import paths, wire upgrade.ts into legacy server

- Fixed import paths in legacy-server.ts: ./auth.js → ../auth.js etc.
  (broken by rename from server.ts → server/legacy-server.ts)
- Implemented upgrade.ts with extracted WS upgrade + auth logic
- Updated server/server.ts bootstrap docs
- All LEGACY tags verified across frozen files and route stubs
This commit is contained in:
jay 2026-05-15 07:11:08 +02:00
parent f70fd02f08
commit 726223eea0
3 changed files with 55 additions and 29 deletions

View File

@ -21,10 +21,10 @@ import {
parseCookies, parseCookies,
SESSION_COOKIE, SESSION_COOKIE,
validateToken, validateToken,
} from "./auth.js"; } from "../auth.js";
import { parseBindAddress, readRemoteControlConfig } from "./config.js"; import { parseBindAddress, readRemoteControlConfig } from "../config.js";
import { buildHTML } from "./html.js"; import { buildHTML } from "../html.js";
import { buildSyncMessage } from "./messages.js"; import { buildSyncMessage } from "../messages.js";
interface WsClient { interface WsClient {
readyState: number; readyState: number;
@ -55,6 +55,8 @@ const wsModule = _require("ws") as {
}; };
const { WebSocketServer, OPEN } = wsModule; const { WebSocketServer, OPEN } = wsModule;
import { handleUpgrade } from "./upgrade.js";
export interface RemoteServer { export interface RemoteServer {
broadcast: (msg: object) => void; broadcast: (msg: object) => void;
sync: (ctx: ExtensionContext) => void; sync: (ctx: ExtensionContext) => void;
@ -205,20 +207,7 @@ export async function startServer(
httpServer.on( httpServer.on(
"upgrade", "upgrade",
(request: IncomingMessage, socket: Socket, head: Buffer) => { (request: IncomingMessage, socket: Socket, head: Buffer) => {
const url = new URL(request.url, "http://localhost"); handleUpgrade(httpServer, wss, request, socket, head, () => isAuthenticated(request));
if (url.pathname === "/ws") {
// Validate auth: session cookie or token query param
if (!isAuthenticated(request)) {
socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, (ws: WsClient) => {
wss.emit("connection", ws, request);
});
} else {
socket.destroy();
}
}, },
); );

View File

@ -3,6 +3,13 @@
* *
* Creates the HTTP + WebSocket server and wires up legacy routes. * Creates the HTTP + WebSocket server and wires up legacy routes.
* Route placeholders will be populated by T-1.5 / T-1.6 / T-1.7. * Route placeholders will be populated by T-1.5 / T-1.6 / T-1.7.
*
* Architecture:
* server/server.ts this file: bootstrap, exports startServer()
* server/upgrade.ts WebSocket upgrade routing (extracted from legacy)
* server/legacy-server.ts LEGACY: original server implementation,
* to be gradually carved into route modules
* server/routes/ stubs; T-1.5..T-1.7 will implement
*/ */
import type { import type {
ExtensionAPI, ExtensionAPI,
@ -13,7 +20,12 @@ export type { RemoteServer } from "./legacy-server.js";
/** /**
* Start the remote-control server. * Start the remote-control server.
* Currently delegates to the legacy server; route modules will be *
* wired in during T-1.5 T-1.7. * Currently delegates to the legacy server monolith; T-1.5T-1.7 will
* incrementally replace legacy routes with the modular route handlers
* under server/routes/.
*/ */
export { startLegacyServer as startServer }; export const startServer: (
pi: ExtensionAPI,
ctx: ExtensionContext,
) => Promise<import("./legacy-server.js").RemoteServer> = startLegacyServer;

View File

@ -1,5 +1,12 @@
// Legacy WebSocket upgrade routing — to be replaced in T-1.5/T-1.6. /**
* WebSocket upgrade routing validates auth and dispatches to the
* appropriate handler.
*
* LEGACY: currently routes everything to a single /ws endpoint.
* T-1.5/T-1.6: dispatch to topic/session-specific handlers (stream, input, ).
*/
import type { IncomingMessage } from "node:http"; import type { IncomingMessage } from "node:http";
import type { Server } from "node:http";
import type { Socket } from "node:net"; import type { Socket } from "node:net";
// Lightweight ws server interface (compatible with the ws package without types) // Lightweight ws server interface (compatible with the ws package without types)
@ -14,18 +21,36 @@ interface WsServer {
} }
/** /**
* Route WebSocket upgrade requests to the legacy server. * Handle an HTTP upgrade request.
* In Phase 2 this will dispatch to topic/session-specific handlers. *
* @param _httpServer The HTTP server (reserved for T-1.5/T-1.6 per-session dispatch).
* @param wss The WebSocket server.
* @param request Incoming upgrade request.
* @param socket Raw socket.
* @param head First packet bytes.
* @param isAuthed Whether the request passed authentication.
*/ */
export function handleUpgrade( export function handleUpgrade(
_httpServer: Server,
wss: WsServer, wss: WsServer,
request: IncomingMessage, request: IncomingMessage,
socket: Socket, socket: Socket,
head: Buffer, head: Buffer,
isAuthed: boolean,
): void { ): void {
// T-1.5/T-1.6: inspect URL to route to stream/input/session handlers. const url = new URL(request.url ?? "/", "http://localhost");
// For now, delegate everything to the legacy WebSocket server.
wss.handleUpgrade(request, socket, head, (ws) => { // T-1.5/T-1.6: inspect url.pathname to dispatch to stream / input / session handlers.
wss.emit("connection", ws, request); if (url.pathname === "/ws") {
}); if (!isAuthed) {
socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit("connection", ws, request);
});
} else {
socket.destroy();
}
} }