Skip to main content

aiway_plugin/
wasm_types.rs

1//! WASM 插件边界序列化类型
2//!
3//! 定义 Host(网关)与 WASM 插件之间数据交换的格式。
4//! 使用 bincode 序列化,性能优于 JSON。
5
6use crate::http::{self, HeaderName, HeaderValue};
7use serde::{Deserialize, Serialize};
8use std::str::FromStr;
9
10/// 插件钩子 ID
11pub const HOOK_ON_REQUEST: i32 = 1;
12pub const HOOK_ON_REQUEST_BODY: i32 = 2;
13pub const HOOK_ON_RESPONSE: i32 = 3;
14pub const HOOK_ON_RESPONSE_BODY: i32 = 4;
15pub const HOOK_ON_LOGGING: i32 = 5;
16
17/// 传递给 WASM 插件的输入数据
18#[derive(Serialize, Deserialize)]
19pub struct WasmInput {
20    /// 插件配置(JSON 字符串)
21    pub config: String,
22    /// HTTP 头部信息(请求或响应)
23    pub head: Option<WasmHead>,
24    /// Body 数据
25    pub body: Option<Vec<u8>>,
26    /// 请求 ID(仅 logging 阶段使用)
27    pub request_id: Option<String>,
28    /// 请求时间戳(仅 logging 阶段使用)
29    pub request_ts: Option<i64>,
30}
31
32/// HTTP 头部信息的可序列化表示
33#[derive(Serialize, Deserialize)]
34pub struct WasmHead {
35    /// 请求方法(仅请求阶段)
36    pub method: Option<String>,
37    /// 请求 URI(仅请求阶段)
38    pub uri: Option<String>,
39    /// 响应状态码(仅响应阶段)
40    pub status: Option<u16>,
41    /// 头部键值对列表
42    pub headers: Vec<(String, String)>,
43}
44
45impl WasmHead {
46    /// 从请求 Parts 构建
47    pub fn from_request_parts(parts: &http::request::Parts) -> Self {
48        let headers = parts
49            .headers
50            .iter()
51            .filter_map(|(k, v)| v.to_str().ok().map(|v| (k.to_string(), v.to_string())))
52            .collect();
53
54        Self {
55            method: Some(parts.method.to_string()),
56            uri: Some(parts.uri.to_string()),
57            status: None,
58            headers,
59        }
60    }
61
62    /// 从响应 Parts 构建
63    pub fn from_response_parts(parts: &http::response::Parts) -> Self {
64        let headers = parts
65            .headers
66            .iter()
67            .filter_map(|(k, v)| v.to_str().ok().map(|v| (k.to_string(), v.to_string())))
68            .collect();
69
70        Self {
71            method: None,
72            uri: None,
73            status: Some(parts.status.as_u16()),
74            headers,
75        }
76    }
77
78    /// 将修改应用到请求 Parts
79    pub fn apply_to_request_parts(&self, parts: &mut http::request::Parts) {
80        if let Some(ref method) = self.method
81            && let Ok(m) = method.parse()
82        {
83            parts.method = m;
84        }
85        if let Some(ref uri) = self.uri
86            && let Ok(u) = uri.parse()
87        {
88            parts.uri = u;
89        }
90        apply_headers(&self.headers, &mut parts.headers);
91    }
92
93    /// 将修改应用到响应 Parts
94    pub fn apply_to_response_parts(&self, parts: &mut http::response::Parts) {
95        if let Some(status) = self.status && let Ok(s) = http::StatusCode::from_u16(status) {
96                parts.status = s;
97            }
98        apply_headers(&self.headers, &mut parts.headers);
99    }
100}
101
102/// 将 WasmHead 中的 headers 应用到 http::HeaderMap
103fn apply_headers(wasm_headers: &[(String, String)], header_map: &mut http::HeaderMap) {
104    header_map.clear();
105    for (k, v) in wasm_headers {
106        if let (Ok(name), Ok(value)) = (HeaderName::from_str(k), HeaderValue::from_str(v)) {
107            header_map.insert(name, value);
108        }
109    }
110}
111
112/// WASM 插件返回的输出数据
113#[derive(Serialize, Deserialize)]
114pub struct WasmOutput {
115    /// 修改后的 HTTP 头部(None 表示不修改)
116    pub head: Option<WasmHead>,
117    /// 修改后的 Body(None 表示不修改)
118    pub body: Option<Vec<u8>>,
119}
120
121/// WASM 插件元信息(由 plugin_info 导出返回)
122#[derive(Serialize, Deserialize)]
123pub struct WasmPluginInfo {
124    pub name: String,
125    pub version: String,
126    pub description: String,
127    /// 默认配置(JSON 字符串)
128    pub default_config: String,
129    /// 插件文档
130    pub readme: Option<String>,
131}