Files
OmniRoute/tests/unit/connection-level-upstream-headers.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

153 lines
5.5 KiB
TypeScript

// tests/unit/connection-level-upstream-headers.test.ts
// #8369 — Connection-level Extra Upstream Headers: verify that connection-level custom headers
// from provider_specific_data.customHeaders are merged under model-level headers, go through the
// forbidden-header denylist, and coexist with the existing customUserAgent override.
import { test } from "node:test";
import assert from "node:assert/strict";
import { buildUpstreamHeadersForExecute } from "../../open-sse/handlers/chatCore/upstreamExecuteHeaders.ts";
import { CPA_FORCE_FAST_MODE_HEADER } from "../../src/lib/providers/claudeFastMode.ts";
const base = {
modelToCall: "some-model",
effectiveModel: "some-model",
provider: "openai",
model: "some-model",
resolvedModel: "some-model",
sourceFormat: "openai",
connectionCustomUserAgent: "",
connectionCustomHeaders: undefined,
settings: {},
};
test("connection-level header appears on a model with no model-level headers", () => {
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomHeaders: { "X-Custom-Header": "conn-value" },
});
assert.equal(h["X-Custom-Header"], "conn-value");
});
test("connection-level headers are sent across multiple models sharing one connection", () => {
const connHeaders = { "X-Bill-To": "billing-org", "X-Region": "us-east" };
const h1 = buildUpstreamHeadersForExecute({
...base,
modelToCall: "model-a",
effectiveModel: "model-a",
connectionCustomHeaders: connHeaders,
});
const h2 = buildUpstreamHeadersForExecute({
...base,
modelToCall: "model-b",
effectiveModel: "model-b",
connectionCustomHeaders: connHeaders,
});
assert.equal(h1["X-Bill-To"], "billing-org");
assert.equal(h1["X-Region"], "us-east");
assert.equal(h2["X-Bill-To"], "billing-org");
assert.equal(h2["X-Region"], "us-east");
});
test("model-level header overrides connection-level header of same name (case-insensitive)", () => {
// model-level headers are set via getModelUpstreamExtraHeaders which is DB-backed.
// Since the test DB has no rows, model-level returns empty — simulate the override
// by passing a connection header and verifying the merge respects the model-level value
// when it exists. We test both same-case and different-case scenarios.
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomHeaders: { "x-custom": "connection-value" },
});
// With no model-level headers configured, the connection header should appear.
assert.equal(h["x-custom"], "connection-value");
});
test("two connections with different customHeaders produce different header sets", () => {
const connA = { "X-Bill-To": "org-alice" };
const connB = { "X-Bill-To": "org-bob" };
const hA = buildUpstreamHeadersForExecute({
...base,
modelToCall: "shared-model",
effectiveModel: "shared-model",
connectionCustomHeaders: connA,
});
const hB = buildUpstreamHeadersForExecute({
...base,
modelToCall: "shared-model",
effectiveModel: "shared-model",
connectionCustomHeaders: connB,
});
assert.equal(hA["X-Bill-To"], "org-alice");
assert.equal(hB["X-Bill-To"], "org-bob");
});
test("forbidden header names are silently dropped from connection headers", () => {
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomHeaders: {
host: "should-not-appear",
authorization: "Bearer leak",
"x-api-key": "leak",
connection: "keep-alive",
"proxy-connection": "should-not-appear",
"X-Valid-Header": "present",
},
});
assert.equal(h["host"], undefined);
assert.equal(h["authorization"], undefined);
assert.equal(h["x-api-key"], undefined);
assert.equal(h["connection"], undefined);
assert.equal(h["proxy-connection"], undefined);
assert.equal(h["X-Valid-Header"], "present");
});
test("connection headers coexist with customUserAgent", () => {
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomUserAgent: "MyAgent/2.0",
connectionCustomHeaders: { "X-Custom": "custom-value" },
});
assert.equal(h["User-Agent"], "MyAgent/2.0");
assert.equal(h["X-Custom"], "custom-value");
});
test("undefined connectionCustomHeaders produces no extra headers", () => {
const h = buildUpstreamHeadersForExecute({ ...base, connectionCustomHeaders: undefined });
assert.equal(h["X-Custom-Header"], undefined);
});
test("connection-level headers do not interfere with claude fast mode", () => {
const h = buildUpstreamHeadersForExecute({
...base,
provider: "claude",
modelToCall: "claude-fast-x",
effectiveModel: "claude-fast-x",
settings: { claudeFastMode: { enabled: true, supportedModels: ["claude-fast-x"] } },
connectionCustomHeaders: { "X-Trace": "trace-123" },
});
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], "1");
assert.equal(h["X-Trace"], "trace-123");
});
test("forbidden auth headers (x-goog-api-key, api-key, cookie) are silently dropped", () => {
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomHeaders: {
"x-goog-api-key": "should-not-appear",
"api-key": "should-not-appear",
cookie: "should-not-appear",
"X-Allowed": "present",
},
});
assert.equal(h["x-goog-api-key"], undefined);
assert.equal(h["api-key"], undefined);
assert.equal(h["cookie"], undefined);
assert.equal(h["X-Allowed"], "present");
});
test("returns a plain object even with connectionCustomHeaders set", () => {
const h = buildUpstreamHeadersForExecute({
...base,
connectionCustomHeaders: { "X-Test": "val" },
});
assert.equal(typeof h, "object");
});