2026-04-03 14:59:58 +08:00
|
|
|
use axum::body::{Body, Bytes};
|
|
|
|
|
use axum::http::{HeaderName, HeaderValue, Response};
|
|
|
|
|
|
2026-04-05 20:23:16 +08:00
|
|
|
use crate::constants::CONTROL_EXECUTED_HEADER;
|
|
|
|
|
use crate::control::GatewayControlDecision;
|
2026-04-10 17:44:55 +08:00
|
|
|
use crate::executor::{
|
|
|
|
|
maybe_execute_stream_request, maybe_execute_sync_request, LocalExecutionRequestOutcome,
|
|
|
|
|
};
|
2026-04-05 20:23:16 +08:00
|
|
|
use crate::{AppState, GatewayError};
|
2026-04-03 14:59:58 +08:00
|
|
|
|
|
|
|
|
use super::resolve_execution_runtime_auth_context;
|
|
|
|
|
|
|
|
|
|
pub(crate) fn allows_control_execute_emergency(decision: &GatewayControlDecision) -> bool {
|
|
|
|
|
decision.is_execution_runtime_candidate()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) async fn maybe_execute_via_control(
|
|
|
|
|
state: &AppState,
|
|
|
|
|
parts: &http::request::Parts,
|
|
|
|
|
body_bytes: Bytes,
|
|
|
|
|
trace_id: &str,
|
|
|
|
|
decision: Option<&GatewayControlDecision>,
|
|
|
|
|
require_stream: bool,
|
2026-04-10 17:44:55 +08:00
|
|
|
) -> Result<LocalExecutionRequestOutcome, GatewayError> {
|
2026-04-03 14:59:58 +08:00
|
|
|
let Some(decision) = decision else {
|
2026-04-10 17:44:55 +08:00
|
|
|
return Ok(LocalExecutionRequestOutcome::NoPath);
|
2026-04-03 14:59:58 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut local_decision = decision.clone();
|
|
|
|
|
if let Some(auth_context) = resolve_execution_runtime_auth_context(
|
|
|
|
|
state,
|
|
|
|
|
&local_decision,
|
|
|
|
|
&parts.headers,
|
|
|
|
|
&parts.uri,
|
|
|
|
|
trace_id,
|
|
|
|
|
)
|
|
|
|
|
.await?
|
|
|
|
|
{
|
|
|
|
|
local_decision.auth_context = Some(auth_context);
|
|
|
|
|
local_decision.local_auth_rejection = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let response = if require_stream {
|
2026-04-07 02:50:19 +08:00
|
|
|
maybe_execute_stream_request(state, parts, &body_bytes, trace_id, Some(&local_decision))
|
|
|
|
|
.await?
|
2026-04-03 14:59:58 +08:00
|
|
|
} else {
|
2026-04-07 02:50:19 +08:00
|
|
|
maybe_execute_sync_request(state, parts, &body_bytes, trace_id, Some(&local_decision))
|
|
|
|
|
.await?
|
2026-04-03 14:59:58 +08:00
|
|
|
};
|
|
|
|
|
|
2026-04-10 17:44:55 +08:00
|
|
|
Ok(match response {
|
|
|
|
|
LocalExecutionRequestOutcome::Responded(response) => {
|
|
|
|
|
LocalExecutionRequestOutcome::Responded(mark_control_executed(response))
|
|
|
|
|
}
|
|
|
|
|
LocalExecutionRequestOutcome::Exhausted(outcome) => {
|
|
|
|
|
LocalExecutionRequestOutcome::Exhausted(outcome)
|
|
|
|
|
}
|
|
|
|
|
LocalExecutionRequestOutcome::NoPath => LocalExecutionRequestOutcome::NoPath,
|
|
|
|
|
})
|
2026-04-03 14:59:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mark_control_executed(mut response: Response<Body>) -> Response<Body> {
|
|
|
|
|
response.headers_mut().insert(
|
|
|
|
|
HeaderName::from_static(CONTROL_EXECUTED_HEADER),
|
|
|
|
|
HeaderValue::from_static("true"),
|
|
|
|
|
);
|
|
|
|
|
response
|
|
|
|
|
}
|