Skip to main content

brain_db_sdk/http/
error.rs

1//! The one error type the HTTP client returns.
2
3use std::fmt;
4
5/// A Brain HTTP edge failure. Mirrors the Python/TypeScript `BrainHttpError`:
6/// `status` (`0` for transport failures), `code`, `message`.
7#[derive(Clone, Debug)]
8pub struct BrainHttpError {
9    /// HTTP status, or `0` for a transport failure.
10    pub status: u16,
11    /// Stable error code (`"transport"` for network failures).
12    pub code: String,
13    /// Human-readable message.
14    pub message: String,
15}
16
17impl BrainHttpError {
18    /// A transport-level failure (could not complete the request).
19    pub(crate) fn transport(message: impl Into<String>) -> Self {
20        Self {
21            status: 0,
22            code: "transport".into(),
23            message: message.into(),
24        }
25    }
26
27    /// Parse the edge's `{ "error": { code, message } }` envelope; fall back to
28    /// the raw body when it isn't that shape.
29    pub(crate) fn from_body(status: u16, body: &str) -> Self {
30        let (mut code, mut message) = ("http_error".to_string(), format!("HTTP {status}"));
31        if let Ok(v) = serde_json::from_str::<serde_json::Value>(body) {
32            if let Some(err) = v.get("error") {
33                if let Some(c) = err.get("code").and_then(|c| c.as_str()) {
34                    code = c.to_string();
35                }
36                if let Some(m) = err.get("message").and_then(|m| m.as_str()) {
37                    message = m.to_string();
38                }
39            }
40        } else if !body.is_empty() {
41            message = body.to_string();
42        }
43        Self {
44            status,
45            code,
46            message,
47        }
48    }
49}
50
51impl fmt::Display for BrainHttpError {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "[{} {}] {}", self.status, self.code, self.message)
54    }
55}
56
57impl std::error::Error for BrainHttpError {}