fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only) - #648

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat
Jun 25, 2026
Merged

fix(openai): apply per-PK request overrides on embed/complete/image (not chat only)#648
jarvis9443 merged 1 commit into
mainfrom
fix/per-pk-overrides-nonchat

Conversation

@jarvis9443

@jarvis9443jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

A ProviderKey can carry request overrides — param_renames, param_constraints, default_body_fields, default_headers — that the operator expects applied to every outbound request that key serves. The OpenAI bridge applied them only in chat() / chat_stream() (via prepare_outbound_body + build_request_headers). The other bridge methods — embed(), complete(), generate_image() — built their bodies and headers by hand and silently dropped every override.

So an operator who configured, say, a default_headers entry or a default_body_fields default on a provider key found it applied to /v1/chat/completions but not to /v1/embeddings, /v1/completions, or /v1/images/generations. Same chat-only oversight as AISIX-Cloud#867 (provider attribution), in a different subsystem.

Fix

Route embed() / complete() / generate_image() through the same prepare_outbound_body + build_request_headers helpers chat() already uses. Overrides are per-PK (not per-endpoint) by design — consistent with chat — and the helpers are no-ops when the PK carries none, so behavior is unchanged for the common (no-override) case. build_request_headers keeps its reserved-header protection (an override can't clobber authorization).

Tests

Per-method tests configure a default_body_fields + default_headers override and assert both reach the outbound upstream request (wiremock body + header matchers). Each fails before the fix (overrides dropped → mock unmatched → Err) and passes after. Full aisix-provider-openai suite green (108), clippy + fmt clean.

Follow-up

The raw-HTTP proxy handlers that bypass the bridge and build requests directly — the /v1/responses verbatim-OpenAI path, /v1/rerank, and /v1/audio/* — apply overrides through a separate (proxy-side) mechanism and are a tracked follow-up, not covered here.

Origin: surfaced by a cross-API consistency audit after AISIX-Cloud#867.

Summary by CodeRabbit

  • Bug Fixes
    • Request overrides are now applied consistently across embeddings, completions, and image generation, matching the behavior already used for chat requests.
    • Outbound requests now preserve the expected headers while also merging any configured default or operator-provided headers.
    • Added regression coverage to verify overridden request fields and headers are sent correctly for these endpoints.

…not chat only
The OpenAI bridge applied operator request overrides (param_renames /
param_constraints / default_body_fields / default_headers) only in chat() /
chat_stream() via prepare_outbound_body + build_request_headers. embed(),
complete() and generate_image() built their bodies/headers by hand and silently
dropped every override, so a PK's configured default_headers / default_body_fields
never reached /v1/embeddings, /v1/completions or /v1/images/generations.
Route those three through the same prepare_outbound_body + build_request_headers
that chat() uses. Overrides are per-PK (not per-endpoint) by design, matching
chat; the helpers are no-ops when the PK carries none, so behavior is unchanged
for the common case.
Per-method tests assert a configured default_body_fields + default_headers reach
the outbound request; each fails before the fix (overrides dropped → upstream
mock unmatched → Err) and passes after.
Note: the raw-HTTP proxy handlers that bypass the bridge (the /v1/responses
verbatim-OpenAI path, /v1/rerank, /v1/audio/*) apply overrides via a separate
mechanism and are a tracked follow-up.
@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c13844d7-a5b0-4bae-99b2-19e8447234ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8f758c4 and 9243b17.

📒 Files selected for processing (1)
  • crates/aisix-provider-openai/src/bridge.rs

📝 Walkthrough

Walkthrough

The OpenAI bridge now applies provider-key request overrides to embed(), complete(), and generate_image() when building outbound bodies and headers. New tokio wiremock tests verify the overridden body fields and default headers for /embeddings, /completions, and /images/generations.

Changes

OpenAI request override parity

Layer / File(s)Summary
Outbound request construction
crates/aisix-provider-openai/src/bridge.rs
embed(), complete(), and generate_image() now apply request overrides through shared body and header helpers before sending outbound requests.
Override regression tests
crates/aisix-provider-openai/src/bridge.rs
Three wiremock-backed tokio tests assert overridden body fields and default headers on the outbound embedding, completion, and image-generation requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
E2e Test Quality Review⚠️ WarningCoverage is wiremock-only integration tests, not E2E against real services, and they only exercise the nominal override path.Add a real end-to-end path using the actual upstream/service boundary, plus boundary/error cases (missing/invalid overrides, auth/header conflicts).
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: applying per-provider-key request overrides to embed, complete, and image generation.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Security Check✅ PassedNo security regressions found: key validation and reserved-header protection remain intact, and the change only extends existing override handling to more endpoints.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/per-pk-overrides-nonchat

Comment @coderabbitai help to get the list of available commands.

Sign up for freeto 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.

1 participant

@jarvis9443