diff --git a/packages/web/package.json b/packages/web/package.json index 946ee2a..8309261 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -9,7 +9,7 @@ "preview": "vite preview", "lint": "biome check src/", "lint:fix": "biome check --write src/", - "test": "vitest run --passWithNoTests", + "test": "vitest run --passWithNoTests && node scripts/test-dev-proxy.mjs", "test:coverage": "vitest run --coverage", "test:e2e": "playwright test", "generate:api": "openapi-typescript openapi.json -o src/api/schema.d.ts" diff --git a/packages/web/scripts/test-dev-proxy.mjs b/packages/web/scripts/test-dev-proxy.mjs new file mode 100644 index 0000000..80f9c32 --- /dev/null +++ b/packages/web/scripts/test-dev-proxy.mjs @@ -0,0 +1,41 @@ +// Run: node packages/web/scripts/test-dev-proxy.mjs +import assert from "node:assert/strict"; +import { once } from "node:events"; +import { createServer as createHttpServer } from "node:http"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import { createServer, loadConfigFromFile } from "vite"; + +const root = fileURLToPath(new URL("../", import.meta.url)); +const loaded = await loadConfigFromFile( + { command: "serve", mode: "development" }, + `${root}vite.config.ts`, +); +const proxy = loaded.config.plugins.find((plugin) => plugin.name === "honcho-api-proxy"); + +for (const base of ["/", "/honcho/"]) { + test(`dev proxy forwards requests under ${base}`, async () => { + const upstream = createHttpServer((req, res) => res.end(req.url)); + upstream.listen(0, "127.0.0.1"); + await once(upstream, "listening"); + const vite = await createServer({ + configFile: false, + root, + base, + plugins: [proxy], + optimizeDeps: { noDiscovery: true, include: [] }, + server: { host: "127.0.0.1", port: 0, strictPort: false }, + }); + try { + await vite.listen(); + const response = await fetch( + `http://127.0.0.1:${vite.httpServer.address().port}${base}api/v3/workspaces/list?limit=1`, + { headers: { "X-Honcho-Upstream": `http://127.0.0.1:${upstream.address().port}` } }, + ); + assert.equal(await response.text(), "/v3/workspaces/list?limit=1"); + } finally { + await vite.close(); + await new Promise((resolve) => upstream.close(resolve)); + } + }); +} diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts index 4622347..760c815 100644 --- a/packages/web/vite.config.ts +++ b/packages/web/vite.config.ts @@ -34,7 +34,7 @@ function honchoApiProxy(): Plugin { return { name: "honcho-api-proxy", configureServer(server) { - server.middlewares.use("/api", async (req, res) => { + server.middlewares.use(`${server.config.base.replace(/\/+$/, "")}/api`, async (req, res) => { const upstream = req.headers[HEADER]; if (typeof upstream !== "string" || upstream.trim() === "") { res.statusCode = 421;