Fix OpenAI family local auth to use bearer (#302)

* Fix OpenAI family local auth to use bearer

* test(gateway): fix bearer auth assertions for openai local flows

* test(usage): make local usage status wait resilient

* style(gateway): apply rustfmt to usage test helper

---------

Co-authored-by: fawney19 <elky0401@gmail.com>
This commit is contained in:
RWDai
2026-04-17 11:10:05 +08:00
committed by GitHub
parent 6964729cb7
commit 96a25d058b
15 changed files with 89 additions and 37 deletions

View File

@@ -5,7 +5,8 @@ use serde_json::Value;
use crate::ai_pipeline::planner::candidate_preparation::resolve_candidate_mapped_model;
use crate::ai_pipeline::planner::spec_metadata::local_video_create_spec_metadata;
use crate::ai_pipeline::transport::auth::{
build_passthrough_headers_with_auth, resolve_local_gemini_auth, resolve_local_openai_chat_auth,
build_passthrough_headers_with_auth, resolve_local_gemini_auth,
resolve_local_openai_bearer_auth,
};
use crate::ai_pipeline::transport::url::{
build_gemini_video_predict_long_running_url, build_passthrough_path_url,
@@ -72,7 +73,7 @@ pub(super) async fn resolve_local_video_create_candidate_payload_parts(
}
let auth = match spec.family {
LocalVideoCreateFamily::OpenAi => resolve_local_openai_chat_auth(transport),
LocalVideoCreateFamily::OpenAi => resolve_local_openai_bearer_auth(transport),
LocalVideoCreateFamily::Gemini => resolve_local_gemini_auth(transport),
};
let Some((auth_header, auth_value)) = auth else {

View File

@@ -16,7 +16,8 @@ use crate::ai_pipeline::planner::standard::{
use crate::ai_pipeline::transport::apply_local_header_rules;
use crate::ai_pipeline::transport::auth::{
build_claude_passthrough_headers, build_complete_passthrough_headers_with_auth,
build_openai_passthrough_headers, ensure_upstream_auth_header, resolve_local_openai_chat_auth,
build_openai_passthrough_headers, ensure_upstream_auth_header,
resolve_local_openai_bearer_auth,
};
use crate::ai_pipeline::transport::local_openai_chat_transport_unsupported_reason;
use crate::ai_pipeline::{ConversionMode, ExecutionStrategy, GatewayProviderTransportSnapshot};
@@ -76,7 +77,7 @@ pub(crate) async fn resolve_local_openai_chat_candidate_payload_parts(
planner_state,
transport,
candidate,
resolve_local_openai_chat_auth(transport),
resolve_local_openai_bearer_auth(transport),
OauthPreparationContext {
trace_id,
api_format: "openai:chat",

View File

@@ -24,7 +24,7 @@ use crate::ai_pipeline::transport::apply_local_header_rules;
use crate::ai_pipeline::transport::auth::{
build_claude_passthrough_headers, build_complete_passthrough_headers_with_auth,
build_openai_passthrough_headers, ensure_upstream_auth_header, resolve_local_gemini_auth,
resolve_local_standard_auth,
resolve_local_openai_bearer_auth, resolve_local_standard_auth,
};
use crate::ai_pipeline::transport::local_standard_transport_unsupported_reason_with_network;
use crate::ai_pipeline::{ConversionMode, ExecutionStrategy};
@@ -107,9 +107,8 @@ pub(crate) async fn resolve_local_openai_cli_candidate_payload_parts(
let direct_auth = if same_format {
match provider_api_format {
"gemini:cli" => resolve_local_gemini_auth(transport),
"claude:cli" | "openai:cli" | "openai:compact" => {
resolve_local_standard_auth(transport)
}
"claude:cli" => resolve_local_standard_auth(transport),
"openai:cli" | "openai:compact" => resolve_local_openai_bearer_auth(transport),
_ => None,
}
} else {

View File

@@ -202,7 +202,7 @@ pub(super) async fn maybe_build_local_test_connection_route_response(
let auth = match format_value.as_str() {
"openai:chat" => {
crate::provider_transport::auth::resolve_local_openai_chat_auth(&transport)
crate::provider_transport::auth::resolve_local_openai_bearer_auth(&transport)
.or(oauth_auth.clone())
}
"claude:chat" => crate::provider_transport::auth::resolve_local_standard_auth(&transport)

View File

@@ -87,7 +87,7 @@ async fn gateway_executes_openai_compact_openai_family_upstream_stream_via_local
endpoint_is_active: true,
key_id: "key-openai-compact-finalize-local-1".to_string(),
key_name: "prod".to_string(),
key_auth_type: "bearer".to_string(),
key_auth_type: "api_key".to_string(),
key_is_active: true,
key_api_formats: Some(vec!["openai:compact".to_string()]),
key_allowed_models: None,
@@ -162,7 +162,7 @@ async fn gateway_executes_openai_compact_openai_family_upstream_stream_via_local
"key-openai-compact-finalize-local-1".to_string(),
"provider-openai-compact-finalize-local-1".to_string(),
"prod".to_string(),
"bearer".to_string(),
"api_key".to_string(),
None,
true,
)

View File

@@ -449,7 +449,7 @@ async fn gateway_executes_openai_chat_stream_via_local_openai_cli_cross_format_c
model: String,
stream: bool,
accept: String,
api_key: String,
authorization: String,
x_client_request_id: String,
session_id: String,
conversation_id: String,
@@ -717,9 +717,9 @@ async fn gateway_executes_openai_chat_stream_via_local_openai_cli_cross_format_c
.and_then(|value| value.as_str())
.unwrap_or_default()
.to_string(),
api_key: payload
authorization: payload
.get("headers")
.and_then(|value| value.get("x-api-key"))
.and_then(|value| value.get("authorization"))
.and_then(|value| value.as_str())
.unwrap_or_default()
.to_string(),
@@ -871,8 +871,8 @@ async fn gateway_executes_openai_chat_stream_via_local_openai_cli_cross_format_c
assert!(seen_execution_runtime_request.stream);
assert_eq!(seen_execution_runtime_request.accept, "text/event-stream");
assert_eq!(
seen_execution_runtime_request.api_key,
"sk-upstream-openai-chat-cli"
seen_execution_runtime_request.authorization,
"Bearer sk-upstream-openai-chat-cli"
);
assert_eq!(
seen_execution_runtime_request.x_client_request_id,

View File

@@ -88,7 +88,7 @@ async fn gateway_executes_openai_cli_sync_via_local_decision_gate_with_local_syn
endpoint_is_active: true,
key_id: "key-openai-cli-local-1".to_string(),
key_name: "prod".to_string(),
key_auth_type: "bearer".to_string(),
key_auth_type: "api_key".to_string(),
key_is_active: true,
key_api_formats: Some(vec!["openai:cli".to_string()]),
key_allowed_models: None,
@@ -171,7 +171,7 @@ async fn gateway_executes_openai_cli_sync_via_local_decision_gate_with_local_syn
"key-openai-cli-local-1".to_string(),
"provider-openai-cli-local-1".to_string(),
"prod".to_string(),
"bearer".to_string(),
"api_key".to_string(),
None,
true,
)

View File

@@ -936,7 +936,7 @@ fn ai_pipeline_video_routes_request_preparation_through_request_payload_seams()
"resolve_candidate_mapped_model(",
"build_provider_request_body(",
"build_video_upstream_url(",
"resolve_local_openai_chat_auth(",
"resolve_local_openai_bearer_auth(",
"resolve_local_gemini_auth(",
] {
assert!(

View File

@@ -803,7 +803,7 @@ fn model_fetch_runtime_paths_depend_on_shared_crates_not_local_pure_helpers() {
"execute_execution_runtime_sync_plan(state, None, &plan)",
"resolve_local_standard_auth(",
"resolve_local_gemini_auth(",
"resolve_local_openai_chat_auth(",
"resolve_local_openai_bearer_auth(",
"resolve_local_vertex_api_key_query_auth(",
"apply_local_header_rules(",
"ensure_upstream_auth_header(",

View File

@@ -33,7 +33,8 @@ where
T: UsageReadRepository + ?Sized,
{
let mut stored = None;
for _ in 0..50 {
let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(5);
loop {
stored = repository
.find_by_request_id(request_id)
.await
@@ -44,9 +45,16 @@ where
{
break;
}
if tokio::time::Instant::now() >= deadline {
let observed = stored
.as_ref()
.map(|usage| usage.status.as_str())
.unwrap_or("<missing>");
panic!("usage should reach status {expected_status}, last observed status: {observed}");
}
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
}
stored.unwrap_or_else(|| panic!("usage should reach status {expected_status}"))
stored.expect("usage should be present once the expected status is observed")
}
#[tokio::test]

View File

@@ -214,7 +214,7 @@ async fn gateway_executes_openai_video_delete_via_reconstructed_data_backed_loca
.to_string(),
authorization: payload
.get("headers")
.and_then(|value| value.get("x-api-key"))
.and_then(|value| value.get("authorization"))
.and_then(|value| value.as_str())
.unwrap_or_default()
.to_string(),
@@ -331,7 +331,7 @@ async fn gateway_executes_openai_video_delete_via_reconstructed_data_backed_loca
);
assert_eq!(
seen_execution_runtime_request.authorization,
"sk-upstream-openai-video"
"Bearer sk-upstream-openai-video"
);
let stored_candidates = request_candidate_repository