1#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
2use std::fmt;
3
4#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
5use bitrouter_core::errors::BitrouterError;
6#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
7use warp::reject::Reject;
8
9#[derive(Debug)]
11#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
12pub(crate) struct BitrouterRejection(pub BitrouterError);
13
14#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
15impl fmt::Display for BitrouterRejection {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 write!(f, "{}", self.0)
18 }
19}
20
21#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
22impl Reject for BitrouterRejection {}
23
24#[derive(Debug)]
26#[cfg(feature = "openai")]
27pub(crate) struct BadRequest(pub String);
28
29#[cfg(feature = "openai")]
30impl fmt::Display for BadRequest {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "{}", self.0)
33 }
34}
35
36#[cfg(feature = "openai")]
37impl Reject for BadRequest {}
38
39#[cfg(any(feature = "openai", feature = "anthropic", feature = "google"))]
45pub fn handle_bitrouter_rejection(err: &warp::Rejection) -> Option<warp::http::Response<String>> {
46 use warp::http::StatusCode;
47
48 if let Some(e) = err.find::<BitrouterRejection>() {
49 let (status, error_type) = match &e.0 {
50 BitrouterError::InvalidRequest { .. } | BitrouterError::UnsupportedFeature { .. } => {
51 (StatusCode::BAD_REQUEST, "invalid_request_error")
52 }
53 BitrouterError::AccessDenied { .. } => (StatusCode::FORBIDDEN, "access_denied"),
54 BitrouterError::Cancelled { .. } => (StatusCode::BAD_REQUEST, "cancelled"),
55 BitrouterError::Provider { context, .. } => {
56 let status = context
57 .status_code
58 .and_then(|code| StatusCode::from_u16(code).ok())
59 .unwrap_or(StatusCode::BAD_GATEWAY);
60 (status, "provider_error")
61 }
62 BitrouterError::Transport { .. }
63 | BitrouterError::ResponseDecode { .. }
64 | BitrouterError::InvalidResponse { .. }
65 | BitrouterError::StreamProtocol { .. } => (StatusCode::BAD_GATEWAY, "upstream_error"),
66 };
67
68 let body = serde_json::json!({
69 "error": {
70 "message": e.0.to_string(),
71 "type": error_type,
72 }
73 })
74 .to_string();
75
76 let response = warp::http::Response::builder()
77 .status(status)
78 .header("content-type", "application/json")
79 .body(body)
80 .ok()?;
81
82 return Some(response);
83 }
84
85 #[cfg(feature = "openai")]
86 if let Some(e) = err.find::<BadRequest>() {
87 let body = serde_json::json!({
88 "error": {
89 "message": e.to_string(),
90 "type": "invalid_request_error",
91 }
92 })
93 .to_string();
94
95 let response = warp::http::Response::builder()
96 .status(StatusCode::BAD_REQUEST)
97 .header("content-type", "application/json")
98 .body(body)
99 .ok()?;
100
101 return Some(response);
102 }
103
104 None
105}