Skip to content

feat(providers): add custom API key header name for all provider types#2287

Open
Jesean wants to merge 3 commits intofarion1231:mainfrom
Jesean:feat/custom-api-key-header
Open

feat(providers): add custom API key header name for all provider types#2287
Jesean wants to merge 3 commits intofarion1231:mainfrom
Jesean:feat/custom-api-key-header

Conversation

@Jesean
Copy link
Copy Markdown

@Jesean Jesean commented Apr 24, 2026

Summary

Allow users to customize the HTTP header name used for API key
authentication when adding providers. Supported app types: Claude,
Codex, Gemini
.

Motivation

Some third-party providers (e.g. those using `x-api-key` or other
custom headers) cannot be used with the default `Authorization: Bearer`
scheme. This change allows those providers to be configured with an
arbitrary header name.

Behavior

  • Default (unchanged): `Authorization: Bearer `
  • Custom header set (e.g. `x-api-key`): `x-api-key: ` —
    the raw key value is sent directly, without the `Bearer` prefix
  • Companion headers from the adapter (e.g. `x-goog-api-client` for
    Gemini, Copilot-specific headers) are preserved — only the
    `authorization` header is replaced

Scope

Custom header is supported for Claude, Codex, and Gemini only.
OpenCode, OpenClaw, and Hermes run from `settingsConfig` rather than
`provider.meta`, so the feature is intentionally excluded from those
forms to avoid a silent no-op.

Changes

Backend (Rust)

  • `src/types.ts` / `provider.rs` — add `apiKeyHeaderName` to `ProviderMeta`
  • `auth.rs` — add `custom_auth_header: Option` to `AuthInfo`
  • `forwarder.rs` — universal injection: reads `meta.api_key_header_name`,
    replaces only the `authorization` header while keeping all other
    adapter headers intact
  • `claude.rs` — also honors `custom_auth_header` within the Claude adapter

Frontend (TypeScript)

  • New shared component `ApiKeyHeaderSection` — toggle button + input field +
    reset to default, reused by Claude, Codex, and Gemini forms
  • `ApiKeyHeaderSection` placed after `ApiKeySection` (top-level,
    consistent position across all three forms)
  • `ProviderForm.tsx` — removed `appId === "claude"` gate; state and meta
    assembly now apply to Claude, Codex, and Gemini

Test plan

  • Add a custom Codex/Gemini provider, set header name to `x-api-key`,
    verify requests arrive with `x-api-key: ` (no `Bearer` prefix)
  • Leave header name blank → default `Authorization: Bearer` behavior
    unchanged
  • Edit an existing provider with a saved `apiKeyHeaderName` → field
    pre-populated correctly
  • `cargo check` passes
  • `tsc --noEmit` passes
  • `prettier --check` passes

Allow users to specify a custom HTTP header name for API key authentication
when adding providers across all six app types (Claude, Codex, Gemini,
OpenCode, OpenClaw, Hermes).

- Default behavior is unchanged: Authorization: Bearer <key>
- When a custom header name is set (e.g. x-api-key), the proxy sends the
  raw key value directly without the "Bearer" prefix
- Universal injection is handled once in forwarder.rs so all adapters
  benefit without individual changes
- Shared ApiKeyHeaderSection component keeps the UI consistent across forms
- ProviderMeta.apiKeyHeaderName persists the setting to config

Changes:
- src/types.ts: add apiKeyHeaderName to ProviderMeta interface
- src-tauri/src/provider.rs: add api_key_header_name to Rust ProviderMeta
- src-tauri/src/proxy/providers/auth.rs: add custom_auth_header to AuthInfo
- src-tauri/src/proxy/providers/claude.rs: apply custom header in Claude adapter
- src-tauri/src/proxy/forwarder.rs: universal custom header injection before adapter call
- shared/ApiKeyHeaderSection.tsx: new shared UI component (toggle + input + reset)
- All six FormFields components: add ApiKeyHeaderSection after ApiKeySection
- ProviderForm.tsx: wire up state and remove claude-only gate
@farion1231
Copy link
Copy Markdown
Owner

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80d2ca6b91

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/proxy/forwarder.rs Outdated
Comment thread src/components/providers/forms/ProviderForm.tsx
jiyaxin added 2 commits April 27, 2026 11:10
- forwarder.rs: keep adapter companion headers when overriding auth.
  Previously the entire adapter header set was discarded; now only the
  authorization header is replaced, preserving headers like
  x-goog-api-client (Gemini) and Copilot-specific headers.

- Remove custom API key header UI from OpenCode/OpenClaw/Hermes forms.
  These apps run from settingsConfig rather than provider.meta, so the
  field had no effect at runtime. Scope is now limited to Claude/Codex/
  Gemini where meta is the authoritative config source.
@Jesean
Copy link
Copy Markdown
Author

Jesean commented Apr 27, 2026

Both review points have been addressed in 83a59a3:

  1. forwarder.rs — custom header no longer discards the full adapter header set. Now only the authorization header is replaced; companion headers (e.g. x-goog-api-client for Gemini, Copilot-specific headers) are preserved via headers.retain(|(name, _)| name.as_str() != "authorization").

  2. OpenCode / OpenClaw / Hermes — removed the custom header UI and props from all three additive-mode forms. The feature is now scoped to Claude, Codex, and Gemini where provider.meta is the authoritative config source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants