fix(test): update stale origin-header assertion to match current behavior (#1329)

Since e14af08f (#709), the sidecar strips the browser Origin header but
immediately replaces it with `http://127.0.0.1:<port>` (line 1321 of
local-api-server.mjs). This ensures local handlers receive a valid
Origin for CORS while preventing browser-supplied origins from leaking
into server-to-server calls.

The test was written before that commit and still asserted
`originPresent: false`. Update the test to:
  - Assert `originPresent: true` (a localhost origin IS present)
  - Assert `originValue` equals `http://127.0.0.1:<port>` (verify it's
    the replaced localhost origin, not the browser's)
  - Rename the test to describe the actual behavior

npm run test:sidecar: 55/55 pass 
This commit is contained in:
lspassos1
2026-03-09 19:57:49 +00:00
committed by GitHub
parent c5d196f29e
commit 294984d315

View File

@@ -64,8 +64,8 @@ function mockHttpsRequestOnce({ statusCode, headers, body }) {
const original = https.request;
https.request = (_options, onResponse) => {
const req = new EventEmitter();
req.setTimeout = () => {};
req.write = () => {};
req.setTimeout = () => { };
req.write = () => { };
req.destroy = (error) => {
if (error) req.emit('error', error);
};
@@ -175,7 +175,7 @@ test('returns local error directly when cloudFallback is off (default)', async (
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -210,7 +210,7 @@ test('falls back to cloud when cloudFallback is enabled and local handler return
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
cloudFallback: 'true',
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -258,7 +258,7 @@ test('preserves POST body when cloud fallback is triggered after local non-OK re
apiDir: localApi.apiDir,
remoteBase: `http://127.0.0.1:${remotePort}`,
cloudFallback: 'true',
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -301,7 +301,7 @@ test('uses local handler response when local handler succeeds', async () => {
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -326,7 +326,7 @@ test('returns 404 when local route does not exist and cloudFallback is off', asy
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -343,7 +343,7 @@ test('returns 404 when local route does not exist and cloudFallback is off', asy
}
});
test('strips browser origin headers before invoking local handlers', async () => {
test('replaces browser origin with localhost origin for local handlers', async () => {
const remote = await setupRemoteServer();
const localApi = await setupApiDir({
'origin-check.js': `
@@ -352,6 +352,7 @@ test('strips browser origin headers before invoking local handlers', async () =>
return new Response(JSON.stringify({
source: 'local',
originPresent: Boolean(origin),
originValue: origin || null,
}), {
status: 200,
headers: { 'content-type': 'application/json' }
@@ -364,7 +365,7 @@ test('strips browser origin headers before invoking local handlers', async () =>
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -375,7 +376,11 @@ test('strips browser origin headers before invoking local handlers', async () =>
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.source, 'local');
assert.equal(body.originPresent, false);
// Since e14af08f (#709) the server strips the browser Origin but
// immediately replaces it with `http://127.0.0.1:<port>`, so the
// handler does receive an Origin header — just the localhost one.
assert.equal(body.originPresent, true);
assert.equal(body.originValue, `http://127.0.0.1:${port}`);
assert.equal(remote.hits.length, 0);
} finally {
await app.close();
@@ -420,7 +425,7 @@ test('preserves Request body when handler uses fetch(Request)', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -472,7 +477,7 @@ test('returns local handler error when fetch(Request) uses a consumed body', asy
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -503,7 +508,7 @@ test('strips browser origin headers when proxying to cloud fallback (cloudFallba
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
cloudFallback: 'true',
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -535,7 +540,7 @@ test('responds to OPTIONS preflight with CORS headers', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -564,7 +569,7 @@ test('preserves Origin in Vary when gzip compression is applied', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -610,7 +615,7 @@ test('resolves packaged tauri resource layout under _up_/api', async () => {
port: 0,
resourceDir: localResource.resourceDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -638,7 +643,7 @@ test('accepts OLLAMA_API_URL via /api/local-env-update', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -666,7 +671,7 @@ test('accepts OLLAMA_MODEL via /api/local-env-update', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -694,7 +699,7 @@ test('rejects unknown key via /api/local-env-update', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -730,7 +735,7 @@ test('validates OLLAMA_API_URL via /api/local-validate-secret (reachable endpoin
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -769,7 +774,7 @@ test('validates LM Studio style /v1 base URL via /api/local-validate-secret', as
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -809,7 +814,7 @@ test('validates OLLAMA_API_URL via native /api/tags fallback', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -837,7 +842,7 @@ test('validates OLLAMA_MODEL stores model name', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -862,7 +867,7 @@ test('rejects OLLAMA_API_URL with non-http protocol', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -896,7 +901,7 @@ test('treats Cloudflare challenge 403 as soft-pass during secret validation', as
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -929,7 +934,7 @@ test('does not soft-pass provider auth 403 JSON responses even with cf-ray heade
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -956,7 +961,7 @@ test('auth-required behavior unchanged — rejects unauthenticated requests when
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1012,7 +1017,7 @@ test('prefers Brotli compression for payloads larger than 1KB when supported by
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1053,7 +1058,7 @@ test('uses gzip compression when Brotli is unavailable but gzip is accepted', as
port: 0,
apiDir: localApi.apiDir,
remoteBase: remote.remoteBase,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1086,7 +1091,7 @@ test('rejects unauthenticated requests to /api/local-status when token is set',
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1120,7 +1125,7 @@ test('rejects unauthenticated requests to /api/local-traffic-log when token is s
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1146,7 +1151,7 @@ test('rejects unauthenticated requests to /api/local-debug-toggle when token is
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1172,7 +1177,7 @@ test('rejects unauthenticated requests to /api/rss-proxy when token is set', asy
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1198,7 +1203,7 @@ test('allows unauthenticated requests to /api/service-status (health check exemp
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1224,7 +1229,7 @@ test('rss-proxy blocks requests to localhost (SSRF protection)', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1245,7 +1250,7 @@ test('rss-proxy blocks requests to private IP ranges (SSRF protection)', async (
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1273,7 +1278,7 @@ test('rss-proxy blocks non-http protocols (SSRF protection)', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1294,7 +1299,7 @@ test('rss-proxy blocks URLs with credentials (SSRF protection)', async () => {
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1324,7 +1329,7 @@ test('traffic log strips query strings from entries to protect privacy', async (
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();
@@ -1359,7 +1364,7 @@ test('service-status reports bound fallback port after EADDRINUSE recovery', asy
const app = await createLocalApiServer({
port: 46123,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
logger: { log() { }, warn() { }, error() { } },
});
const { port } = await app.start();