feat: add provider websocket http data plane

This commit is contained in:
Codex
2026-05-16 16:03:53 +00:00
parent 659d1c6148
commit 28cc2af121
19 changed files with 545 additions and 22 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@unidesk/provider-gateway",
"version": "0.2.19",
"version": "0.2.20",
"private": true,
"type": "module",
"scripts": {
+39 -1
View File
@@ -5,6 +5,7 @@ import {
type CoreEgressTcpDataMessage,
type CoreEgressTcpOpenedMessage,
type CoreDispatchMessage,
type CoreHttpTunnelRequestMessage,
type CoreHostSshCloseMessage,
type CoreHostSshEofMessage,
type CoreHostSshInputMessage,
@@ -561,7 +562,7 @@ function sendJsonOk(value: unknown): boolean {
}
function sendRegister(): void {
const capabilities = ["heartbeat", "system.status", "docker.status", "docker.ps", "provider.upgrade", "microservice.http", "microservice.http.cache", "echo"];
const capabilities = ["heartbeat", "system.status", "docker.status", "docker.ps", "provider.upgrade", "microservice.http", "microservice.http.cache", "microservice.http.tunnel", "echo"];
if (isHostSshConfigured()) capabilities.push("host.ssh");
if (config.egressProxyEnabled) capabilities.push("network.egress-proxy");
sendJson({
@@ -1989,6 +1990,7 @@ async function runMicroserviceHttp(payload: Record<string, JsonValue>): Promise<
truncated: bounded.truncated,
transform: transformed.transform,
upstreamDurationMs: Date.now() - requestStartedAt,
proxyMode: "provider-gateway-http-fetch",
};
})();
if (cacheable) microserviceHttpInFlight.set(cacheKey, requestPromise);
@@ -2053,6 +2055,38 @@ async function handleDispatch(message: CoreDispatchMessage): Promise<void> {
}
}
async function handleHttpTunnelRequest(message: CoreHttpTunnelRequestMessage): Promise<void> {
const startedAt = Date.now();
try {
const result = await runMicroserviceHttp(message.payload);
sendJson({
type: "http_tunnel_response",
providerId: config.providerId,
requestId: message.requestId,
ok: (result as { ok?: unknown }).ok === true,
result,
at: new Date().toISOString(),
});
logger("debug", "http_tunnel_completed", {
requestId: message.requestId,
serviceId: typeof message.payload.serviceId === "string" ? message.payload.serviceId : "",
durationMs: Date.now() - startedAt,
ok: (result as { ok?: unknown }).ok === true,
});
} catch (error) {
const text = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
logger("error", "http_tunnel_failed", { requestId: message.requestId, error: text });
sendJson({
type: "http_tunnel_response",
providerId: config.providerId,
requestId: message.requestId,
ok: false,
result: { ok: false, error: text },
at: new Date().toISOString(),
});
}
}
function handleMessage(raw: MessageEvent<string>): void {
try {
const parsed = JSON.parse(raw.data) as { type?: unknown };
@@ -2060,6 +2094,10 @@ function handleMessage(raw: MessageEvent<string>): void {
handleDispatch(parsed as CoreDispatchMessage).catch((error) => logger("error", "dispatch_handler_failed", { error: String(error) }));
return;
}
if (parsed.type === "http_tunnel_request") {
handleHttpTunnelRequest(parsed as CoreHttpTunnelRequestMessage).catch((error) => logger("error", "http_tunnel_handler_failed", { error: String(error) }));
return;
}
if (parsed.type === "host_ssh_open") {
startHostSshSession(parsed as CoreHostSshOpenMessage);
return;