Files
dify/knowledge-fs/tools/swagger/server.test.mjs
Jyong 4ee43b8afc chore: migrate knowledge-fs source tree
Import the committed KnowledgeFS snapshot dc4072ee302317145612087ce7440851dc329fd0 under knowledge-fs/ without its Git history, local IDE settings, or build artifacts.
2026-07-20 04:54:20 -04:00

121 lines
4.3 KiB
JavaScript

import assert from "node:assert/strict";
import http from "node:http";
import { test } from "node:test";
import { createSwaggerServer, renderIndexHtml, resolveRoute, upstreamUrl } from "./server.mjs";
function listen(server) {
return new Promise((resolve) => {
server.listen(0, "127.0.0.1", () => {
resolve(server.address().port);
});
});
}
function close(server) {
return new Promise((resolve) => server.close(resolve));
}
test("resolveRoute serves the UI shell only for the root path", () => {
assert.deepEqual(resolveRoute("/"), { kind: "index" });
assert.deepEqual(resolveRoute(""), { kind: "index" });
assert.deepEqual(resolveRoute("/openapi.json"), { kind: "proxy" });
assert.deepEqual(resolveRoute("/knowledge-spaces"), { kind: "proxy" });
});
test("upstreamUrl joins the request path and query onto the API base", () => {
assert.equal(
upstreamUrl("http://localhost:8787", "/openapi.json"),
"http://localhost:8787/openapi.json",
);
assert.equal(
upstreamUrl("http://localhost:8787", "/queries?limit=10"),
"http://localhost:8787/queries?limit=10",
);
});
test("renderIndexHtml loads Swagger UI from the CDN and points at the proxied spec", () => {
const html = renderIndexHtml({ apiBase: "http://localhost:8787" });
assert.match(html, /cdn\.jsdelivr\.net\/npm\/swagger-ui-dist@\d+\.\d+\.\d+/);
assert.match(html, /swagger-ui-bundle\.js/);
assert.match(html, /swagger-ui\.css/);
assert.match(html, /url:\s*"\/openapi\.json"/);
// Same-origin proxy means the browser never needs the raw API base, but we
// surface it so the operator knows what is being proxied.
assert.match(html, /http:\/\/localhost:8787/);
});
test("the proxy forwards method, body, and status to the upstream API", async () => {
const received = [];
const upstream = http.createServer((req, res) => {
const chunks = [];
req.on("data", (c) => chunks.push(c));
req.on("end", () => {
received.push({
method: req.method,
url: req.url,
body: Buffer.concat(chunks).toString(),
});
if (req.url === "/openapi.json") {
res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify({ openapi: "3.1.0" }));
return;
}
if (req.url === "/knowledge-spaces") {
res.writeHead(401, { "content-type": "application/json" });
res.end(JSON.stringify({ error: "Unauthorized" }));
return;
}
res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify({ ok: true }));
});
});
const upstreamPort = await listen(upstream);
const proxy = createSwaggerServer({ apiBase: `http://localhost:${upstreamPort}` });
const proxyPort = await listen(proxy);
const base = `http://127.0.0.1:${proxyPort}`;
try {
const indexRes = await fetch(`${base}/`);
const indexBody = await indexRes.text();
assert.equal(indexRes.status, 200);
assert.match(indexRes.headers.get("content-type") ?? "", /text\/html/);
assert.match(indexBody, /swagger-ui/);
const specRes = await fetch(`${base}/openapi.json`);
assert.equal(specRes.status, 200);
assert.deepEqual(await specRes.json(), { openapi: "3.1.0" });
// Auth failures from the gateway must pass through unchanged (try-it-out).
const authRes = await fetch(`${base}/knowledge-spaces`);
assert.equal(authRes.status, 401);
// Try-it-out POSTs forward method + body.
const postRes = await fetch(`${base}/queries`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ q: "hello" }),
});
assert.equal(postRes.status, 200);
const posted = received.find((r) => r.url === "/queries");
assert.equal(posted.method, "POST");
assert.deepEqual(JSON.parse(posted.body), { q: "hello" });
} finally {
await close(proxy);
await close(upstream);
}
});
test("the proxy returns 502 when the upstream gateway is unreachable", async () => {
// Point at a port nothing is listening on.
const proxy = createSwaggerServer({ apiBase: "http://127.0.0.1:1" });
const proxyPort = await listen(proxy);
try {
const res = await fetch(`http://127.0.0.1:${proxyPort}/health`);
assert.equal(res.status, 502);
assert.match(await res.text(), /gateway unreachable/);
} finally {
await close(proxy);
}
});