vtx_sdk/host/
http.rs

1//! Host-side HTTP request/response helpers.
2
3use crate::bindings::vtx::api::{
4    stream_io,
5    types::{HttpRequest, HttpResponse},
6};
7use crate::error::VtxError;
8
9/// 标准化请求与响应类型别名(与 WIT 接口对齐)
10pub type Request = HttpRequest;
11pub type Response = HttpResponse;
12
13/// HTTP 响应构造器(适用于插件运行时)
14///
15/// 提供以下构造能力:
16/// - 成功响应(JSON)
17/// - 错误响应(自动映射状态码与结构体)
18/// - 文件流响应(基于宿主 UUID 打开文件)
19/// - 状态码响应(纯状态码,无 body)
20///
21pub struct ResponseBuilder;
22
23impl ResponseBuilder {
24    /// 构造 JSON 响应(200 OK)
25    ///
26    /// ⚠️ 若序列化失败,返回 `[]` 作为兜底内容,**不表示逻辑成功**。
27    pub fn json<T: serde::Serialize>(data: &T) -> Response {
28        let json_bytes = serde_json::to_vec(data).unwrap_or_else(|_| b"[]".to_vec());
29
30        // 使用宿主提供的内存缓冲区封装 JSON 数据
31        let buffer = stream_io::create_memory_buffer(&json_bytes);
32        HttpResponse {
33            status: 200,
34            body: Some(buffer),
35        }
36    }
37
38    /// 构造错误响应(根据错误类型自动映射 HTTP 状态码)
39    ///
40    /// - `AuthDenied(code)` → `code`(401 / 403)
41    /// - `NotFound(_)` → 404
42    /// - `PermissionDenied(_)` → 403
43    /// - `SerializationError(_)` → 400
44    /// - `DatabaseError(_)`, `Internal(_)` → 500
45    ///
46    /// 返回结构:
47    /// ```json
48    /// {
49    ///   "success": false,
50    ///   "error": true,
51    ///   "code": 403,
52    ///   "type": "PermissionDenied",
53    ///   "message": "You are not allowed to access this resource"
54    /// }
55    /// ```
56    pub fn error(err: VtxError) -> Response {
57        let (status, message) = match &err {
58            VtxError::AuthDenied(code) => (*code, format!("Authentication failed: {}", err)),
59            VtxError::NotFound(msg) => (404, msg.clone()),
60            VtxError::PermissionDenied(msg) => (403, msg.clone()),
61            VtxError::SerializationError(msg) => (400, format!("Bad Request: {}", msg)),
62            VtxError::DatabaseError(msg) => (500, format!("Database Error: {}", msg)),
63            VtxError::Internal(msg) => (500, format!("Internal Error: {}", msg)),
64        };
65
66        let error_body = serde_json::json!({
67            "success": false,                  // 统一布尔失败标识
68            "error": true,                     // 标识为错误响应
69            "code": status,                    // 映射的 HTTP 状态码
70            "type": format!("{:?}", err),      // 错误类型(调试使用)
71            "message": message                 // 错误消息(用户可见)
72        });
73
74        let mut resp = Self::json(&error_body);
75        resp.status = status;
76        resp
77    }
78
79    /// 构造文件流响应(通过宿主接口按 UUID 打开)
80    ///
81    /// - 成功:200 + 文件内容流
82    /// - 失败:返回 404 JSON 错误响应
83    pub fn file(uuid: &str) -> Response {
84        match stream_io::open_file(uuid) {
85            Ok(buffer) => HttpResponse {
86                status: 200,
87                body: Some(buffer),
88            },
89            Err(e) => Self::error(VtxError::NotFound(format!("File UUID not found: {}", e))),
90        }
91    }
92
93    /// 构造纯状态码响应(无 body)
94    ///
95    /// 用于如:204 No Content、403 Forbidden 等响应场景
96    pub fn status(code: u16) -> Response {
97        HttpResponse {
98            status: code,
99            body: None,
100        }
101    }
102
103    /// 构造标准 404 Not Found 响应(无正文)
104    pub fn not_found() -> Response {
105        Self::status(404)
106    }
107}