feat: propagate Google upstream errors to client
When Google returns an error (400, 429, 500, etc.), the MITM proxy now captures it and the API handlers return it immediately instead of hanging until timeout. - UpstreamError struct stored in MitmStore - MITM proxy parses Google error JSON (message + status) - Polling handler checks for upstream errors each cycle - Streaming handlers emit response.failed / SSE error events - Error status mapped to OpenAI-style types (invalid_request_error, rate_limit_error, authentication_error, server_error, etc.) - All handlers clear stale errors at request start
This commit is contained in:
@@ -25,6 +25,28 @@ pub(crate) fn err_response(
|
||||
(status, Json(body)).into_response()
|
||||
}
|
||||
|
||||
/// Convert a MITM-captured upstream error from Google into an HTTP response.
|
||||
/// Maps Google's HTTP status codes and preserves the error message.
|
||||
pub(crate) fn upstream_err_response(err: &crate::mitm::store::UpstreamError) -> axum::response::Response {
|
||||
// Map Google's status code to HTTP status
|
||||
let status = StatusCode::from_u16(err.status).unwrap_or(StatusCode::BAD_GATEWAY);
|
||||
|
||||
// Map Google error status to OpenAI-style error type
|
||||
let error_type = match err.error_status.as_deref() {
|
||||
Some("INVALID_ARGUMENT") => "invalid_request_error",
|
||||
Some("RESOURCE_EXHAUSTED") => "rate_limit_error",
|
||||
Some("PERMISSION_DENIED") | Some("UNAUTHENTICATED") => "authentication_error",
|
||||
Some("NOT_FOUND") => "not_found_error",
|
||||
Some("INTERNAL") | Some("UNAVAILABLE") => "server_error",
|
||||
_ => "upstream_error",
|
||||
};
|
||||
|
||||
let message = err.message.clone()
|
||||
.unwrap_or_else(|| format!("Google API returned HTTP {}", err.status));
|
||||
|
||||
err_response(status, message, error_type)
|
||||
}
|
||||
|
||||
pub(crate) fn now_unix() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
||||
Reference in New Issue
Block a user