refactor: 移除 Python upstream 依赖,清理全部 legacy/Python 兼容层

- 移除 upstream_base_url 参数及 AETHER_GATEWAY_UPSTREAM 环境变量,gateway 不再需要指向 Python 宿主
- 删除所有 LEGACY_*/PYTHON_* 常量、路由组、header 定义及 sunset/phaseout 机制
- 将 legacy_gateway_bridge 重命名为 internal_gateway,executor 相关命名统一为 execution_runtime
- dev.sh 新增 Postgres/Redis 预检查,移除 upstream 相关启动参数和提示
- 新增 ai_public 路由处理器
- 全量适配 handler、test、state、control 等模块的命名和接口变更
This commit is contained in:
fawney19
2026-04-04 01:40:24 +08:00
parent 1d9c77522a
commit cbc811f6ce
484 changed files with 11046 additions and 3925 deletions

View File

@@ -1,12 +1,38 @@
use super::*;
use crate::gateway::ai_pipeline::{planner as ai_planner, runtime as ai_runtime};
use super::{
attach_execution_path_header, build_internal_control_error_response,
build_internal_finalize_decision, build_internal_gateway_fallback_plan_payload,
build_internal_gateway_header_map, build_internal_gateway_passthrough_payload,
build_internal_gateway_proxy_public_response, build_internal_gateway_request_parts,
build_internal_gateway_resolve_payload, build_internal_gateway_uri,
build_internal_tunnel_heartbeat_ack, build_management_token_payload, gateway_error_message,
maybe_build_internal_finalize_video_response, parse_internal_tunnel_heartbeat_request,
parse_internal_tunnel_node_status_request,
};
use crate::gateway::ai_pipeline::planner as ai_planner;
use crate::gateway::constants::{
CONTROL_EXECUTED_HEADER, EXECUTION_PATH_EXECUTION_RUNTIME_STREAM,
EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
};
use crate::gateway::handlers::{
InternalGatewayAuthContextRequest, InternalGatewayExecuteRequest, InternalGatewayResolveRequest,
};
use crate::gateway::{
execute_execution_runtime_stream, execute_execution_runtime_sync,
maybe_build_stream_plan_payload, maybe_build_sync_finalize_outcome,
maybe_build_sync_plan_payload, AppState, GatewayControlDecision, GatewayError,
GatewayPublicRequestContext, ProxyNodeHeartbeatMutation, ProxyNodeTunnelStatusMutation,
};
use axum::body::{Body, Bytes};
use axum::http::{self, HeaderName, HeaderValue, Response};
use axum::response::IntoResponse;
use axum::Json;
use serde_json::json;
pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
state: &AppState,
request_context: &GatewayPublicRequestContext,
remote_addr: &std::net::SocketAddr,
request_body: Option<&axum::body::Bytes>,
legacy_internal_gateway_allowed: bool,
request_body: Option<&Bytes>,
) -> Result<Option<Response<Body>>, GatewayError> {
let Some(decision) = request_context.control_decision.as_ref() else {
return Ok(None);
@@ -14,17 +40,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
if decision.route_class.as_deref() != Some("internal_proxy") {
return Ok(None);
}
if decision.route_family.as_deref() == Some("gateway_legacy") {
if !legacy_internal_gateway_allowed {
return Ok(Some(build_retired_internal_gateway_response()));
}
state.record_fallback_metric(
GatewayFallbackMetricKind::LegacyInternalBridge,
Some(decision),
None,
Some("legacy_internal_bridge"),
GatewayFallbackReason::LegacyInternalGateway,
);
if decision.route_family.as_deref() == Some("internal_gateway") {
if !remote_addr.ip().is_loopback() {
return Ok(Some(build_internal_control_error_response(
http::StatusCode::FORBIDDEN,
@@ -40,7 +56,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayResolveRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayResolveRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -95,7 +111,8 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayAuthContextRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayAuthContextRequest>(request_body)
{
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -115,7 +132,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
let mut synthetic_decision = GatewayControlDecision::synthetic(
"/",
Some("internal_proxy".to_string()),
Some("gateway_legacy".to_string()),
Some("internal_gateway".to_string()),
Some("auth_context".to_string()),
Some(payload.auth_endpoint_signature),
);
@@ -145,7 +162,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -247,7 +264,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -270,6 +287,12 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
.as_deref()
.unwrap_or(request_context.trace_id.as_str())
.to_string();
let body_is_empty = payload.body_base64.is_none()
&& payload
.body_json
.as_object()
.map(|value| value.is_empty())
.unwrap_or(false);
let Some(mut resolved) = crate::gateway::resolve_control_route(
state,
&parts.method,
@@ -341,7 +364,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -370,10 +393,6 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
.as_object()
.map(|value| value.is_empty())
.unwrap_or(false);
let body_bytes = match decode_legacy_gateway_request_body_bytes(&payload) {
Ok(bytes) => bytes,
Err(response) => return Ok(Some(response)),
};
let Some(mut resolved) = crate::gateway::resolve_control_route(
state,
&parts.method,
@@ -405,20 +424,6 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
}
return Ok(Some(Json(planned).into_response()));
}
if let Some(executed_response) = ai_runtime::maybe_execute_sync_request(
state,
&parts,
&body_bytes,
trace_id.as_str(),
Some(&resolved),
)
.await?
{
return Ok(Some(attach_execution_path_header(
executed_response,
EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
)));
}
return Ok(Some(build_internal_gateway_proxy_public_response()));
}
Some("plan_stream")
@@ -431,7 +436,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -454,10 +459,6 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
.as_deref()
.unwrap_or(request_context.trace_id.as_str())
.to_string();
let body_bytes = match decode_legacy_gateway_request_body_bytes(&payload) {
Ok(bytes) => bytes,
Err(response) => return Ok(Some(response)),
};
let Some(mut resolved) = crate::gateway::resolve_control_route(
state,
&parts.method,
@@ -487,20 +488,6 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
}
return Ok(Some(Json(planned).into_response()));
}
if let Some(executed_response) = ai_runtime::maybe_execute_stream_request(
state,
&parts,
&body_bytes,
trace_id.as_str(),
Some(&resolved),
)
.await?
{
return Ok(Some(attach_execution_path_header(
executed_response,
EXECUTION_PATH_EXECUTION_RUNTIME_STREAM,
)));
}
return Ok(Some(build_internal_gateway_proxy_public_response()));
}
Some("execute_sync")
@@ -513,7 +500,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -536,10 +523,12 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
.as_deref()
.unwrap_or(request_context.trace_id.as_str())
.to_string();
let body_bytes = match decode_legacy_gateway_request_body_bytes(&payload) {
Ok(bytes) => bytes,
Err(response) => return Ok(Some(response)),
};
let body_is_empty = payload.body_base64.is_none()
&& payload
.body_json
.as_object()
.map(|value| value.is_empty())
.unwrap_or(false);
let Some(mut resolved) = crate::gateway::resolve_control_route(
state,
&parts.method,
@@ -562,7 +551,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
&resolved,
&payload.body_json,
payload.body_base64.as_deref(),
body_bytes.is_empty(),
body_is_empty,
)
.await?
{
@@ -589,21 +578,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
}
}
}
if let Some(executed_response) = ai_runtime::maybe_execute_sync_request(
state,
&parts,
&body_bytes,
trace_id.as_str(),
Some(&resolved),
)
.await?
{
return Ok(Some(attach_execution_path_header(
executed_response,
EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
)));
}
return Ok(None);
return Ok(Some(build_internal_gateway_proxy_public_response()));
}
Some("execute_stream")
if request_context.request_path == "/api/internal/gateway/execute-stream" =>
@@ -615,7 +590,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
};
let payload =
match serde_json::from_slice::<LegacyGatewayExecuteRequest>(request_body) {
match serde_json::from_slice::<InternalGatewayExecuteRequest>(request_body) {
Ok(payload) => payload,
Err(_) => {
return Ok(Some(build_internal_control_error_response(
@@ -638,10 +613,6 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
.as_deref()
.unwrap_or(request_context.trace_id.as_str())
.to_string();
let body_bytes = match decode_legacy_gateway_request_body_bytes(&payload) {
Ok(bytes) => bytes,
Err(response) => return Ok(Some(response)),
};
let Some(mut resolved) = crate::gateway::resolve_control_route(
state,
&parts.method,
@@ -688,21 +659,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
}
}
}
if let Some(executed_response) = ai_runtime::maybe_execute_stream_request(
state,
&parts,
&body_bytes,
trace_id.as_str(),
Some(&resolved),
)
.await?
{
return Ok(Some(attach_execution_path_header(
executed_response,
EXECUTION_PATH_EXECUTION_RUNTIME_STREAM,
)));
}
return Ok(None);
return Ok(Some(build_internal_gateway_proxy_public_response()));
}
Some("report_sync")
if request_context.request_path == "/api/internal/gateway/report-sync" =>
@@ -773,7 +730,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
)));
}
};
let Some(synthetic_decision) = build_legacy_finalize_decision(&payload) else {
let Some(synthetic_decision) = build_internal_finalize_decision(&payload) else {
return Ok(Some(build_internal_control_error_response(
http::StatusCode::BAD_REQUEST,
"Unsupported gateway sync finalize kind",
@@ -797,7 +754,7 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
);
return Ok(Some(response));
}
if let Some(response) = maybe_build_legacy_finalize_video_response(
if let Some(response) = maybe_build_internal_finalize_video_response(
state,
trace_id.as_str(),
&synthetic_decision,
@@ -812,7 +769,12 @@ pub(crate) async fn maybe_build_local_internal_proxy_response_impl(
"Unsupported gateway sync finalize kind",
)));
}
_ => return Ok(None),
_ => {
return Ok(Some(build_internal_control_error_response(
http::StatusCode::NOT_FOUND,
"unsupported internal gateway route",
)));
}
}
}
if !remote_addr.ip().is_loopback() {

View File

@@ -1,25 +1,30 @@
use super::*;
pub(crate) fn build_retired_internal_gateway_response() -> Response<Body> {
attach_legacy_internal_gateway_deprecation_headers(
(
http::StatusCode::GONE,
Json(json!({
"detail": "legacy internal gateway route removed; use public proxy",
})),
)
.into_response(),
)
}
use crate::gateway::constants::{
CONTROL_ACTION_HEADER, CONTROL_ACTION_PROXY_PUBLIC, CONTROL_EXECUTED_HEADER,
CONTROL_EXECUTION_RUNTIME_CANDIDATE_KEY, EXECUTION_PATH_CONTROL_EXECUTE_STREAM,
EXECUTION_PATH_CONTROL_EXECUTE_SYNC, EXECUTION_PATH_DISTRIBUTED_OVERLOADED,
EXECUTION_PATH_EXECUTION_RUNTIME_STREAM, EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
EXECUTION_PATH_HEADER, EXECUTION_PATH_LOCAL_AUTH_DENIED, EXECUTION_PATH_LOCAL_OVERLOADED,
EXECUTION_PATH_LOCAL_RATE_LIMITED, EXECUTION_PATH_PUBLIC_PROXY_PASSTHROUGH,
};
use crate::gateway::handlers::admin::build_internal_control_error_response;
use crate::gateway::handlers::{
unix_secs_to_rfc3339, InternalTunnelHeartbeatRequest, InternalTunnelNodeStatusRequest,
};
use crate::gateway::{AppState, GatewayControlDecision, GatewayError, StoredProxyNode};
use aether_data::repository::management_tokens::{
StoredManagementToken, StoredManagementTokenUserSummary,
};
use axum::body::Body;
use axum::http::{self, header::HeaderName, header::HeaderValue, Response};
use axum::response::IntoResponse;
use axum::Json;
use serde_json::{json, Value};
use std::collections::BTreeMap;
fn insert_execution_runtime_candidate_fields(
payload: &mut serde_json::Map<String, serde_json::Value>,
value: bool,
) {
payload.insert(
CONTROL_LEGACY_EXECUTION_RUNTIME_CANDIDATE_KEY.to_string(),
json!(value),
);
payload.insert(
CONTROL_EXECUTION_RUNTIME_CANDIDATE_KEY.to_string(),
json!(value),
@@ -85,32 +90,12 @@ pub(crate) fn build_internal_gateway_fallback_plan_payload(
}
pub(crate) fn build_internal_gateway_proxy_public_response() -> Response<Body> {
attach_legacy_internal_gateway_deprecation_headers(
(
http::StatusCode::CONFLICT,
[(CONTROL_ACTION_HEADER, CONTROL_ACTION_PROXY_PUBLIC)],
Json(json!({ "action": CONTROL_ACTION_PROXY_PUBLIC })),
)
.into_response(),
(
http::StatusCode::CONFLICT,
[(CONTROL_ACTION_HEADER, CONTROL_ACTION_PROXY_PUBLIC)],
Json(json!({ "action": CONTROL_ACTION_PROXY_PUBLIC })),
)
}
pub(crate) fn attach_legacy_internal_gateway_deprecation_headers(
mut response: Response<Body>,
) -> Response<Body> {
response.headers_mut().insert(
HeaderName::from_static(LEGACY_INTERNAL_GATEWAY_PHASEOUT_HEADER),
HeaderValue::from_static(LEGACY_INTERNAL_GATEWAY_PHASEOUT_STATUS),
);
response.headers_mut().insert(
HeaderName::from_static(LEGACY_INTERNAL_GATEWAY_SUNSET_DATE_HEADER),
HeaderValue::from_static(LEGACY_INTERNAL_GATEWAY_SUNSET_DATE),
);
response.headers_mut().insert(
HeaderName::from_static("sunset"),
HeaderValue::from_static(LEGACY_INTERNAL_GATEWAY_SUNSET_HTTP_DATE),
);
response
.into_response()
}
pub(crate) fn attach_execution_path_header(
@@ -141,51 +126,11 @@ pub(crate) fn resolve_local_proxy_execution_path(
Some(EXECUTION_PATH_LOCAL_RATE_LIMITED) => EXECUTION_PATH_LOCAL_RATE_LIMITED,
Some(EXECUTION_PATH_LOCAL_OVERLOADED) => EXECUTION_PATH_LOCAL_OVERLOADED,
Some(EXECUTION_PATH_DISTRIBUTED_OVERLOADED) => EXECUTION_PATH_DISTRIBUTED_OVERLOADED,
Some(EXECUTION_PATH_PUBLIC_PROXY_AFTER_EXECUTION_RUNTIME_MISS)
| Some(LEGACY_EXECUTION_PATH_PUBLIC_PROXY_AFTER_EXECUTION_RUNTIME_MISS) => {
EXECUTION_PATH_PUBLIC_PROXY_AFTER_EXECUTION_RUNTIME_MISS
}
Some(EXECUTION_PATH_PUBLIC_PROXY_PASSTHROUGH) => EXECUTION_PATH_PUBLIC_PROXY_PASSTHROUGH,
_ => default_execution_path,
}
}
pub(crate) fn decode_legacy_gateway_request_body_bytes(
payload: &LegacyGatewayExecuteRequest,
) -> Result<Bytes, Response<Body>> {
if let Some(body_base64) = payload.body_base64.as_deref() {
let decoded = base64::engine::general_purpose::STANDARD
.decode(body_base64)
.map_err(|_| {
build_internal_control_error_response(
http::StatusCode::BAD_REQUEST,
"invalid internal gateway body payload",
)
})?;
return Ok(Bytes::from(decoded));
}
let body_json = payload.body_json.clone();
if body_json.is_null() {
return Ok(Bytes::new());
}
if body_json
.as_object()
.map(|value| value.is_empty())
.unwrap_or(false)
{
return Ok(Bytes::new());
}
let encoded = serde_json::to_vec(&body_json).map_err(|_| {
build_internal_control_error_response(
http::StatusCode::BAD_REQUEST,
"invalid internal gateway body payload",
)
})?;
Ok(Bytes::from(encoded))
}
pub(crate) fn build_internal_gateway_header_map(
headers: &BTreeMap<String, String>,
) -> Result<http::HeaderMap, Response<Body>> {
@@ -267,7 +212,7 @@ pub(crate) fn build_internal_gateway_uri(
})
}
fn infer_legacy_finalize_signature(
fn infer_internal_finalize_signature(
payload: &crate::gateway::GatewaySyncReportRequest,
) -> Option<String> {
let report_context = payload.report_context.as_ref()?;
@@ -317,10 +262,10 @@ fn infer_legacy_finalize_signature(
None
}
pub(crate) fn build_legacy_finalize_decision(
pub(crate) fn build_internal_finalize_decision(
payload: &crate::gateway::GatewaySyncReportRequest,
) -> Option<GatewayControlDecision> {
let signature = infer_legacy_finalize_signature(payload)?;
let signature = infer_internal_finalize_signature(payload)?;
let (public_path, route_family, route_kind) = match signature.as_str() {
"openai:chat" => ("/v1/chat/completions", "openai", "chat"),
"openai:cli" => ("/v1/responses", "openai", "cli"),
@@ -345,10 +290,10 @@ pub(crate) fn build_legacy_finalize_decision(
)
}
fn build_legacy_finalize_video_plan(
fn build_internal_finalize_video_plan(
payload: &crate::gateway::GatewaySyncReportRequest,
) -> Option<aether_contracts::ExecutionPlan> {
let signature = infer_legacy_finalize_signature(payload)?;
let signature = infer_internal_finalize_signature(payload)?;
if !matches!(signature.as_str(), "openai:video" | "gemini:video") {
return None;
}
@@ -380,9 +325,9 @@ fn build_legacy_finalize_video_plan(
.cloned()
.unwrap_or_else(|| json!({}));
let url = match signature.as_str() {
"openai:video" => "https://legacy.internal.invalid/v1/videos".to_string(),
"openai:video" => "https://internal.gateway.invalid/v1/videos".to_string(),
"gemini:video" => format!(
"https://legacy.internal.invalid/v1beta/models/{}:predictLongRunning",
"https://internal.gateway.invalid/v1beta/models/{}:predictLongRunning",
model_name.clone().unwrap_or_else(|| "veo-3".to_string())
),
_ => return None,
@@ -393,17 +338,17 @@ fn build_legacy_finalize_video_plan(
candidate_id: None,
provider_name: Some(provider_name.clone()),
provider_id: context_text("provider_id")
.unwrap_or_else(|| format!("legacy-{provider_name}-video-provider")),
.unwrap_or_else(|| format!("internal-{provider_name}-video-provider")),
endpoint_id: context_text("endpoint_id")
.unwrap_or_else(|| format!("legacy-{provider_name}-video-endpoint")),
.unwrap_or_else(|| format!("internal-{provider_name}-video-endpoint")),
key_id: context_text("key_id")
.or_else(|| context_text("api_key_id"))
.unwrap_or_else(|| format!("legacy-{provider_name}-video-key")),
.unwrap_or_else(|| format!("internal-{provider_name}-video-key")),
method: "POST".to_string(),
url,
headers: std::collections::BTreeMap::from([(
"authorization".to_string(),
"Bearer legacy-internal-gateway".to_string(),
"Bearer internal-gateway".to_string(),
)]),
content_type: Some("application/json".to_string()),
content_encoding: None,
@@ -425,10 +370,10 @@ fn build_legacy_finalize_video_plan(
})
}
fn build_legacy_finalize_video_request_path(
fn build_internal_finalize_video_request_path(
payload: &crate::gateway::GatewaySyncReportRequest,
) -> Option<String> {
let signature = infer_legacy_finalize_signature(payload)?;
let signature = infer_internal_finalize_signature(payload)?;
let report_context = payload.report_context.as_ref().and_then(Value::as_object);
let context_text = |key: &str| {
report_context
@@ -475,13 +420,13 @@ fn build_legacy_finalize_video_request_path(
}
}
pub(crate) async fn maybe_build_legacy_finalize_video_response(
pub(crate) async fn maybe_build_internal_finalize_video_response(
state: &AppState,
trace_id: &str,
decision: &GatewayControlDecision,
payload: &crate::gateway::GatewaySyncReportRequest,
) -> Result<Option<Response<Body>>, GatewayError> {
let Some(plan) = build_legacy_finalize_video_plan(payload) else {
let Some(plan) = build_internal_finalize_video_plan(payload) else {
return Ok(None);
};
@@ -520,7 +465,7 @@ pub(crate) async fn maybe_build_legacy_finalize_video_response(
if let Some(mut response) =
crate::gateway::maybe_build_local_sync_finalize_response(trace_id, decision, payload)?
{
if let Some(request_path) = build_legacy_finalize_video_request_path(payload) {
if let Some(request_path) = build_internal_finalize_video_request_path(payload) {
state
.video_tasks
.apply_finalize_mutation(request_path.as_str(), payload.report_kind.as_str());

View File

@@ -1,6 +1,9 @@
pub(crate) use super::*;
use super::admin::build_internal_control_error_response;
mod gateway_helpers;
pub(crate) use self::gateway_helpers::*;
use self::gateway_helpers::*;
pub(crate) use self::gateway_helpers::{
build_management_token_payload, resolve_local_proxy_execution_path,
};
mod gateway;
pub(crate) use self::gateway::maybe_build_local_internal_proxy_response_impl;