codex_helper_core/proxy/
entrypoint.rs1use std::time::Instant;
2
3use axum::body::Body;
4use axum::http::{Request, Response, StatusCode};
5use tracing::instrument;
6
7use super::ProxyService;
8use super::provider_execution::{
9 ExecuteProviderChainParams, ProviderExecutionOutcome,
10 execute_provider_chain_with_route_executor, log_retry_options,
11};
12use super::request_context::prepare_proxy_request;
13use super::request_failures::finish_failed_proxy_request;
14use super::retry::retry_info_for_failed_attempts;
15use super::route_unavailability::route_unavailable_response_for_request;
16
17#[instrument(skip_all, fields(service = %proxy.service_name))]
18pub async fn handle_proxy(
19 proxy: ProxyService,
20 req: Request<Body>,
21) -> Result<Response<Body>, (StatusCode, String)> {
22 let start = Instant::now();
23 let started_at_ms = std::time::SystemTime::now()
24 .duration_since(std::time::UNIX_EPOCH)
25 .map(|d| d.as_millis() as u64)
26 .unwrap_or(0);
27
28 let prepared = prepare_proxy_request(&proxy, req, &start, started_at_ms).await?;
29 log_retry_options(proxy.service_name, prepared.request_id, &prepared.plan);
30 let provider_chain_params = ExecuteProviderChainParams {
31 proxy: &proxy,
32 route_selection: &prepared.route_selection,
33 method: &prepared.method,
34 uri: &prepared.uri,
35 client_headers: &prepared.client_headers,
36 client_headers_entries_cache: &prepared.client_headers_entries_cache,
37 client_uri: prepared.client_uri.as_str(),
38 start: &start,
39 started_at_ms,
40 request_id: prepared.request_id,
41 request_body_len: prepared.request_body_len,
42 body_for_upstream: &prepared.body_for_upstream,
43 request_model: prepared.request_model.as_deref(),
44 session_binding: prepared.session_binding.as_ref(),
45 session_override_config: prepared.session_override_config.as_deref(),
46 global_station_override: prepared.global_station_override.as_deref(),
47 override_model: prepared.override_model.as_deref(),
48 override_effort: prepared.override_effort.as_deref(),
49 override_service_tier: prepared.override_service_tier.as_deref(),
50 effective_effort: prepared.effective_effort.as_deref(),
51 effective_service_tier: prepared.effective_service_tier.as_deref(),
52 base_service_tier: &prepared.base_service_tier,
53 session_id: prepared.session_id.as_deref(),
54 session_identity_source: prepared.session_identity_source,
55 cwd: prepared.cwd.as_deref(),
56 request_flavor: &prepared.request_flavor,
57 request_body_previews: prepared.request_body_previews,
58 debug_max: prepared.debug_max,
59 warn_max: prepared.warn_max,
60 client_body_debug: prepared.client_body_debug.as_ref(),
61 client_body_warn: prepared.client_body_warn.as_ref(),
62 plan: &prepared.plan,
63 cooldown_backoff: prepared.cooldown_backoff,
64 };
65 let provider_execution =
66 execute_provider_chain_with_route_executor(provider_chain_params).await;
67 let (upstream_chain, route_attempts, last_err) = match provider_execution {
68 ProviderExecutionOutcome::Return(response) => return Ok(response),
69 ProviderExecutionOutcome::Exhausted(state) => {
70 (state.upstream_chain, state.route_attempts, state.last_err)
71 }
72 };
73
74 let dur = start.elapsed().as_millis() as u64;
75 let retry = retry_info_for_failed_attempts(&upstream_chain, &route_attempts);
76 let (status, msg) = last_err.unwrap_or_else(|| {
77 (
78 StatusCode::BAD_GATEWAY,
79 "no upstreams available".to_string(),
80 )
81 });
82
83 let failure = finish_failed_proxy_request(super::request_failures::FailedProxyRequestParams {
84 proxy: &proxy,
85 method: &prepared.method,
86 path: prepared.uri.path(),
87 request_id: prepared.request_id,
88 status,
89 message: msg,
90 duration_ms: dur,
91 started_at_ms,
92 session_id: prepared.session_id.clone(),
93 session_identity_source: prepared.session_identity_source,
94 cwd: prepared.cwd.clone(),
95 effective_effort: prepared.effective_effort.clone(),
96 service_tier: prepared.base_service_tier.clone(),
97 codex_bridge: prepared.request_flavor.codex_bridge_log.clone(),
98 retry,
99 failure_route_attempts: route_attempts.clone(),
100 })
101 .await;
102
103 if let Some(response) = route_unavailable_response_for_request(
104 &prepared.request_flavor,
105 failure.1.as_str(),
106 &route_attempts,
107 ) {
108 return Ok(response);
109 }
110
111 Err(failure)
112}