sa_token_plugin_ntex/
adapter.rs

1use ntex::web::HttpRequest;
2use sa_token_adapter::context::{SaRequest, SaResponse, CookieOptions};
3use serde::Serialize;
4
5/// 中文: 将 Ntex HttpRequest 封装为 SaRequest 适配器
6/// English: Adapter wrapping Ntex HttpRequest to implement SaRequest
7pub struct NtexRequestAdapter<'a> {
8    request: &'a HttpRequest,
9}
10
11impl<'a> NtexRequestAdapter<'a> {
12    /// 中文: 创建适配器实例
13    /// English: Creates a new adapter instance
14    pub fn new(request: &'a HttpRequest) -> Self {
15        Self { request }
16    }
17}
18
19impl<'a> SaRequest for NtexRequestAdapter<'a> {
20    /// 中文: 读取指定 Header
21    /// English: Retrieves specified header value
22    fn get_header(&self, name: &str) -> Option<String> {
23        self.request.headers().get(name)
24            .and_then(|v| v.to_str().ok())
25            .map(|s| s.to_string())
26    }
27
28    /// 中文: 解析 Cookie 并返回指定名称的值
29    /// English: Parses cookies and returns the value by name
30    fn get_cookie(&self, name: &str) -> Option<String> {
31        self.request.headers().get("cookie")
32            .and_then(|v| v.to_str().ok())
33            .and_then(|cookies| {
34                cookies.split(';')
35                    .find_map(|cookie| {
36                        let mut parts = cookie.trim().splitn(2, '=');
37                        match (parts.next(), parts.next()) {
38                            (Some(k), Some(v)) if k == name => Some(v.to_string()),
39                            _ => None,
40                        }
41                    })
42            })
43    }
44
45    /// 中文: 支持路径参数和查询参数读取
46    /// English: Supports reading both path and query parameters
47    fn get_param(&self, name: &str) -> Option<String> {
48        self.request.match_info().get(name)
49            .map(|s| s.to_string())
50            .or_else(|| {
51                self.request.query_string()
52                    .split('&')
53                    .find_map(|pair| {
54                        let mut parts = pair.splitn(2, '=');
55                        match (parts.next(), parts.next()) {
56                            (Some(k), Some(v)) if k == name => 
57                                urlencoding::decode(v).ok().map(|s| s.to_string()),
58                            _ => None,
59                        }
60                    })
61            })
62    }
63
64    /// 中文: 返回请求路径
65    /// English: Returns request path
66    fn get_path(&self) -> String {
67        self.request.path().to_string()
68    }
69
70    /// 中文: 返回请求方法
71    /// English: Returns request method
72    fn get_method(&self) -> String {
73        self.request.method().to_string()
74    }
75
76    /// 中文: 提取客户端 IP
77    /// English: Extracts client IP address
78    fn get_client_ip(&self) -> Option<String> {
79        self.request.peer_addr()
80            .map(|addr| addr.ip().to_string())
81    }
82}
83
84/// 中文: 响应适配器,用于设置响应头和 JSON 内容
85/// English: Response adapter for setting headers and JSON body
86pub struct NtexResponseAdapter {
87    headers: Vec<(String, String)>,
88    body: Option<String>,
89}
90
91impl NtexResponseAdapter {
92    /// 中文: 初始化空响应适配器
93    /// English: Initializes an empty response adapter
94    pub fn new() -> Self {
95        Self {
96            headers: Vec::new(),
97            body: None,
98        }
99    }
100}
101
102impl Default for NtexResponseAdapter {
103    fn default() -> Self {
104        Self::new()
105    }
106}
107
108impl SaResponse for NtexResponseAdapter {
109    /// 中文: 设置响应头
110    /// English: Sets response header
111    fn set_header(&mut self, name: &str, value: &str) {
112        self.headers.push((name.to_string(), value.to_string()));
113    }
114
115    /// 中文: 写入 Cookie(简单实现,可按需扩展)
116    /// English: Stores cookie header (simple implementation, extend as needed)
117    fn set_cookie(&mut self, name: &str, value: &str, _options: CookieOptions) {
118        self.headers.push(("Set-Cookie".to_string(), format!("{}={}", name, value)));
119    }
120
121    /// 中文: 状态码在 Ntex 响应构建阶段处理
122    /// English: Status code handled during Ntex response building
123    fn set_status(&mut self, _status: u16) {}
124
125    /// 中文: 设置 JSON 响应
126    /// English: Sets JSON response body
127    fn set_json_body<T: Serialize>(&mut self, body: T) -> Result<(), serde_json::Error> {
128        let json = serde_json::to_string(&body)?;
129        self.body = Some(json);
130        self.headers.push(("Content-Type".to_string(), "application/json".to_string()));
131        Ok(())
132    }
133}
134