Skip to main content

codex_helper_core/proxy/
entrypoint.rs

1use 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}