fix: support Cloud Web internal API port
This commit is contained in:
@@ -299,6 +299,7 @@ async function resolveServices(serviceIds, catalog) {
|
||||
function runtimeScriptBase64() {
|
||||
const source = String.raw`
|
||||
import { createServer } from "node:http";
|
||||
import http from "node:http";
|
||||
import { spawn } from "node:child_process";
|
||||
import { readFile, stat } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
@@ -364,6 +365,36 @@ function copyHeaders(headers) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function requestUpstream(target, request, body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const upstream = http.request(
|
||||
target,
|
||||
{
|
||||
method: request.method,
|
||||
headers: {
|
||||
accept: request.headers.accept || "application/json",
|
||||
"content-type": request.headers["content-type"] || "application/json",
|
||||
"content-length": Buffer.byteLength(body)
|
||||
}
|
||||
},
|
||||
(upstreamResponse) => {
|
||||
const chunks = [];
|
||||
upstreamResponse.on("data", (chunk) => chunks.push(chunk));
|
||||
upstreamResponse.on("end", () => {
|
||||
resolve({
|
||||
statusCode: upstreamResponse.statusCode || 502,
|
||||
headers: upstreamResponse.headers,
|
||||
body: Buffer.concat(chunks)
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
upstream.on("error", reject);
|
||||
if (body) upstream.write(body);
|
||||
upstream.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function proxyCloudApi(request, response, url) {
|
||||
if (!cloudApiBaseUrl) {
|
||||
sendJson(response, 503, {
|
||||
@@ -401,20 +432,21 @@ async function proxyCloudApi(request, response, url) {
|
||||
}
|
||||
|
||||
const target = new URL(url.pathname + url.search, cloudApiBaseUrl);
|
||||
const upstream = await fetch(target, {
|
||||
method: request.method,
|
||||
headers: {
|
||||
accept: request.headers.accept || "application/json",
|
||||
"content-type": request.headers["content-type"] || "application/json"
|
||||
},
|
||||
body: request.method === "GET" ? undefined : body
|
||||
});
|
||||
const payload = Buffer.from(await upstream.arrayBuffer());
|
||||
response.writeHead(upstream.status, {
|
||||
...copyHeaders(Object.fromEntries(upstream.headers.entries())),
|
||||
"content-length": payload.length
|
||||
});
|
||||
response.end(payload);
|
||||
try {
|
||||
const upstream = await requestUpstream(target, request, request.method === "GET" ? "" : body);
|
||||
response.writeHead(upstream.statusCode, {
|
||||
...copyHeaders(upstream.headers),
|
||||
"content-length": upstream.body.length
|
||||
});
|
||||
response.end(upstream.body);
|
||||
} catch (error) {
|
||||
sendJson(response, 502, {
|
||||
error: "cloud_api_proxy_failed",
|
||||
serviceId,
|
||||
target: target.href.replace(/\/\/[^/@]*@/u, "//***@"),
|
||||
reason: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function serveCloudWeb() {
|
||||
|
||||
@@ -51,11 +51,15 @@ assert.match(app, /callRpc\("audit\.event\.query"/);
|
||||
assert.match(app, /callRpc\("evidence\.record\.query"/);
|
||||
assert.match(artifactPublisher, /HWLAB_API_BASE_URL/);
|
||||
assert.match(artifactPublisher, /readOnlyRpcMethods/);
|
||||
assert.match(artifactPublisher, /requestUpstream/);
|
||||
assert.match(artifactPublisher, /from "node:http"/);
|
||||
assert.doesNotMatch(artifactPublisher, /await fetch\(target/);
|
||||
assert.match(artifactPublisher, /"system\.health"/);
|
||||
assert.match(artifactPublisher, /"cloud\.adapter\.describe"/);
|
||||
assert.match(artifactPublisher, /"audit\.event\.query"/);
|
||||
assert.match(artifactPublisher, /"evidence\.record\.query"/);
|
||||
assert.match(artifactPublisher, /readonly_rpc_required/);
|
||||
assert.match(artifactPublisher, /cloud_api_proxy_failed/);
|
||||
assert.match(app, /degraded/);
|
||||
assert.match(app, /runtime\.serviceRoute\.join\(" -> "\)/);
|
||||
assert.doesNotMatch(app, /callRpc\("hardware\./);
|
||||
|
||||
Reference in New Issue
Block a user