aether/builtins/
network.rs

1// src/builtins/network.rs
2//! 网络IO操作函数
3
4use crate::evaluator::RuntimeError;
5use crate::value::Value;
6
7/// 辅助函数:安全地获取字符串参数
8fn get_string(val: &Value) -> Result<String, RuntimeError> {
9    match val {
10        Value::String(s) => Ok(s.clone()),
11        _ => Err(RuntimeError::TypeErrorDetailed {
12            expected: "String".to_string(),
13            got: format!("{:?}", val),
14        }),
15    }
16}
17
18/// HTTP GET 请求
19///
20/// # 参数
21/// - URL
22///
23/// # 返回
24/// 响应内容(字符串)
25///
26/// # 安全性
27/// 需要启用网络权限
28pub fn http_get(args: &[Value]) -> Result<Value, RuntimeError> {
29    if args.is_empty() {
30        return Err(RuntimeError::WrongArity {
31            expected: 1,
32            got: 0,
33        });
34    }
35
36    let url = get_string(&args[0])?;
37
38    // 使用 ureq 进行简单的 HTTP 请求
39    match ureq::get(&url).call() {
40        Ok(response) => match response.into_body().read_to_string() {
41            Ok(body) => Ok(Value::String(body)),
42            Err(e) => Err(RuntimeError::CustomError(format!(
43                "Failed to read response body: {}",
44                e
45            ))),
46        },
47        Err(e) => Err(RuntimeError::CustomError(format!(
48            "HTTP GET request failed: {}",
49            e
50        ))),
51    }
52}
53
54/// HTTP POST 请求
55///
56/// # 参数
57/// - URL
58/// - 请求体(字符串)
59/// - 可选:Content-Type(默认 "application/json")
60///
61/// # 返回
62/// 响应内容(字符串)
63///
64/// # 安全性
65/// 需要启用网络权限
66pub fn http_post(args: &[Value]) -> Result<Value, RuntimeError> {
67    if args.len() < 2 {
68        return Err(RuntimeError::WrongArity {
69            expected: 2,
70            got: args.len(),
71        });
72    }
73
74    let url = get_string(&args[0])?;
75    let body = get_string(&args[1])?;
76    let content_type = if args.len() > 2 {
77        get_string(&args[2])?
78    } else {
79        "application/json".to_string()
80    };
81
82    match ureq::post(&url)
83        .header("Content-Type", &content_type)
84        .send(body.as_bytes())
85    {
86        Ok(response) => match response.into_body().read_to_string() {
87            Ok(resp_body) => Ok(Value::String(resp_body)),
88            Err(e) => Err(RuntimeError::CustomError(format!(
89                "Failed to read response body: {}",
90                e
91            ))),
92        },
93        Err(e) => Err(RuntimeError::CustomError(format!(
94            "HTTP POST request failed: {}",
95            e
96        ))),
97    }
98}
99
100/// HTTP PUT 请求
101///
102/// # 参数
103/// - URL
104/// - 请求体(字符串)
105/// - 可选:Content-Type(默认 "application/json")
106///
107/// # 返回
108/// 响应内容(字符串)
109///
110/// # 安全性
111/// 需要启用网络权限
112pub fn http_put(args: &[Value]) -> Result<Value, RuntimeError> {
113    if args.len() < 2 {
114        return Err(RuntimeError::WrongArity {
115            expected: 2,
116            got: args.len(),
117        });
118    }
119
120    let url = get_string(&args[0])?;
121    let body = get_string(&args[1])?;
122    let content_type = if args.len() > 2 {
123        get_string(&args[2])?
124    } else {
125        "application/json".to_string()
126    };
127
128    match ureq::put(&url)
129        .header("Content-Type", &content_type)
130        .send(body.as_bytes())
131    {
132        Ok(response) => match response.into_body().read_to_string() {
133            Ok(resp_body) => Ok(Value::String(resp_body)),
134            Err(e) => Err(RuntimeError::CustomError(format!(
135                "Failed to read response body: {}",
136                e
137            ))),
138        },
139        Err(e) => Err(RuntimeError::CustomError(format!(
140            "HTTP PUT request failed: {}",
141            e
142        ))),
143    }
144}
145
146/// HTTP DELETE 请求
147///
148/// # 参数
149/// - URL
150///
151/// # 返回
152/// 响应内容(字符串)
153///
154/// # 安全性
155/// 需要启用网络权限
156pub fn http_delete(args: &[Value]) -> Result<Value, RuntimeError> {
157    if args.is_empty() {
158        return Err(RuntimeError::WrongArity {
159            expected: 1,
160            got: 0,
161        });
162    }
163
164    let url = get_string(&args[0])?;
165
166    match ureq::delete(&url).call() {
167        Ok(response) => match response.into_body().read_to_string() {
168            Ok(body) => Ok(Value::String(body)),
169            Err(e) => Err(RuntimeError::CustomError(format!(
170                "Failed to read response body: {}",
171                e
172            ))),
173        },
174        Err(e) => Err(RuntimeError::CustomError(format!(
175            "HTTP DELETE request failed: {}",
176            e
177        ))),
178    }
179}