LibreChat/api/server/controllers
Danny Avila 2350ebb24a
📨 feat: Custom Headers on Built-in Provider Endpoints (#13742)
* 📨 feat: Custom Headers on Built-in Provider Endpoints

Add a `headers` config option to the built-in `openAI`, `anthropic`, and
`google` endpoints (incl. Anthropic/Google Vertex), mirroring the custom
endpoint header mechanism. Values support the same placeholder resolution
(env vars, `{{LIBRECHAT_USER_*}}`, `{{LIBRECHAT_BODY_CONVERSATIONID}}`) and
are resolved at request time so dynamic values like conversationId resolve
against the live request — without losing provider-native request shaping.

Closes #13082. Covers #13713: forwarding conversationId to a reverse proxy
is now `X-Conversation-Id: '{{LIBRECHAT_BODY_CONVERSATIONID}}'` — an unknown
header is ignored by the native Anthropic API, so no 400 and no metadata
gating needed.

- Schema: `headers` on `baseEndpointSchema` (openAI/google/anthropic/all).
- New `mergeHeaders`/`resolveConfigHeaders` utils centralize the per-provider
  header locations (`configuration.defaultHeaders`, Anthropic
  `clientOptions.defaultHeaders`, Google `customHeaders`); provider-managed
  headers (auth, `anthropic-beta`) always win on collision.
- Each initializer threads configured headers (endpoint over `all`) into the
  right place; request-time resolution runs across all locations in the main
  and title flows.

* 🩹 fix: Cast endpoints.all to TEndpoint for headers DeepPartial widening

Adding `headers` (a Record) to `baseEndpointSchema` makes `DeepPartial<TCustomConfig>`
widen its value type to `string | undefined`, which is not assignable to the
concrete `TEndpoint['headers']: Record<string, string>` at the `loadedEndpoints.all`
assignment. Cast at the assignment site, mirroring the existing
`anthropicConfig as TAnthropicEndpoint` cast in the same function.

* 🛡️ fix: Harden built-in endpoint custom headers (Codex review)

Address Codex P2 findings on the custom-headers feature:

- Anthropic title requests: `omitTitleOptions` strips the `clientOptions`
  carrier, which dropped its `defaultHeaders`. Preserve just the header carrier
  so gateway/reverse-proxy metadata still reaches title generation.
- mergeHeaders: match header names case-insensitively so an override (e.g. a
  provider-managed `Authorization`/`anthropic-beta`) replaces/uniones a
  case-variant from the base instead of emitting two names a client may collapse.
- OpenAI: withhold admin-configured headers when the user supplies the base URL
  (`user_provided`), since values may carry `${SECRET}`/token placeholders that
  must not reach a user-controlled endpoint — mirrors the custom-endpoint guard.
- Azure: honor global `endpoints.all` headers (same OpenAI carrier) while keeping
  Azure-managed `api-key`/version headers authoritative.

Adds tests for each.

* 🔐 fix: Resolve-once + provider-managed header safety (Codex review round 2)

Address Codex P2 findings:

- Azure: keep global `endpoints.all` headers unresolved at init and let
  request-time `resolveConfigHeaders` resolve them once, avoiding a
  second-order env expansion of already-substituted user values.
- Google: `resolveConfigHeaders` no longer template-resolves the
  provider-managed `Authorization` header (built from a possibly user-provided
  key), so a user key like `${ENV}` can't leak server environment values.
- Model fetches: thread configured headers (endpoint over `all`) + user object
  through `getOpenAIModels`/`getAnthropicModels` → `fetchModels`, so a
  gateway-fronted built-in provider receives the header on `/models` too. Fixed
  `fetchModels` to merge custom headers for Anthropic instead of overwriting
  them (managed `x-api-key`/version still win).

Adds/updates tests for each.

* 🧯 fix: Header provenance, memory/title coverage, idempotency (Codex round 3)

Address Codex P2 findings, including two regressions from the prior round:

- Google auth (findings 6 & 8): move native Google header resolution to init
  (`initializeGoogle`), resolving admin templates BEFORE the key-derived auth
  header is built. resolveConfigHeaders no longer touches Google `customHeaders`,
  so admin `Authorization` templates resolve again (fixes the round-2 regression)
  while the SDK auth header (possibly a user-provided key) is never env-expanded.
- Memory runs: memory extraction now calls `resolveConfigHeaders`, so native
  Anthropic (and OpenAI) headers resolve for memory requests too.
- Vertex titles: restore the ORIGINAL `clientOptions` object reference (not a
  copy) when preserving headers across `omitTitleOptions`, so the Vertex
  `createClient` closure and the resolved headers stay on the same object.
- Reuse: `resolveConfigHeaders` is now idempotent (resolve-once per header map),
  preventing a second pass from env-expanding values already substituted with
  user/body data when an agent object flows through buildAgentInput twice.

Adds/updates tests for each.
2026-06-14 17:02:04 -04:00
..
__tests__ 🤫 refactor: Silent MCP OAuth Refresh on Mid-Session 401 (#13369) 2026-06-10 13:12:42 -04:00
agents 📨 feat: Custom Headers on Built-in Provider Endpoints (#13742) 2026-06-14 17:02:04 -04:00
assistants 🔐 feat: Add Signed CloudFront File Downloads (#12970) 2026-05-06 19:48:30 -04:00
auth 🤝 fix: Honor OPENID_REUSE_TOKENS in Admin OAuth Exchange (#13154) 2026-05-18 09:34:58 -04:00
AuthController.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
AuthController.spec.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
Balance.js 🤫 chore: Quiet Repetitive Log Noise from Balance, CloudFront, and Capability Paths (#13461) 2026-06-01 20:40:16 -04:00
Balance.spec.js 🤫 chore: Quiet Repetitive Log Noise from Balance, CloudFront, and Capability Paths (#13461) 2026-06-01 20:40:16 -04:00
EndpointController.js refactor: Integrate Capabilities into Agent File Uploads and Tool Handling (#5048) 2024-12-19 13:04:48 -05:00
FavoritesController.js 📌 feat: Add Pin Support for Model Specs (#11219) 2026-04-09 18:37:25 -04:00
FavoritesController.spec.js 📌 feat: Add Pin Support for Model Specs (#11219) 2026-04-09 18:37:25 -04:00
mcp.js 🗄️ fix: Gate Request-Scoped MCP Servers Out of Persistent Tool Cache (#13672) 2026-06-13 11:26:49 -04:00
ModelController.js 🏗️ refactor: Remove Redundant Caching, Migrate Config Services to TypeScript (#12466) 2026-03-30 16:49:48 -04:00
PermissionsController.js 🪪 fix: Filter ACL Principal Details (#13524) 2026-06-05 19:06:41 -04:00
PluginController.js 🪪 fix: Resolve Group-Scoped Config Overrides (#13176) 2026-05-18 10:16:20 -04:00
PluginController.spec.js 🪪 fix: Resolve Group-Scoped Config Overrides (#13176) 2026-05-18 10:16:20 -04:00
SkillStatesController.js 🗂️ feat: Add Deployment Skill Directory (#13523) 2026-06-05 10:24:28 -04:00
TokenConfigController.js 📊 feat: Real-Time Context Window & Token Usage Tracking (#13670) 2026-06-13 19:38:28 -04:00
tools.js 🧯 fix: Harden Data Retention Semantics (#13049) 2026-05-19 21:58:42 -04:00
TwoFactorController.js 🔑 fix: Require OTP Verification for 2FA Re-Enrollment and Backup Code Regeneration (#12223) 2026-03-14 01:51:31 -04:00
UserController.js 🤫 refactor: Silent MCP OAuth Refresh on Mid-Session 401 (#13369) 2026-06-10 13:12:42 -04:00
UserController.spec.js 🛂 fix: Normalize Verification Flow Error Responses (#13558) 2026-06-06 15:08:43 -04:00