1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use mlua::{Lua, UserData};
use reqwest::Url;
use serde_json::Value as JsonValue;
use crate::http::req::RequestBuilder;
pub struct HttpClient {
pub base_url: Option<String>,
}
impl HttpClient {
pub fn new() -> Self {
Self { base_url: None }
}
}
impl UserData for HttpClient {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method_mut("base_url", |_, this, url: String| {
let parsed = Url::parse(&url).map_err(|e| {
mlua::Error::RuntimeError(format!(
"invalid base_url `{url}`: {e}. expected absolute URL like `https://api.example.com`"
))
})?;
let scheme = parsed.scheme();
if scheme != "http" && scheme != "https" {
return Err(mlua::Error::RuntimeError(format!(
"invalid base_url `{url}`: unsupported scheme `{scheme}`. only `http` and `https` are allowed"
)));
}
if parsed.host_str().is_none() {
return Err(mlua::Error::RuntimeError(format!(
"invalid base_url `{url}`: host is missing"
)));
}
this.base_url = Some(parsed.to_string());
Ok(())
});
methods.add_method("req", |_, this, ()| {
Ok(RequestBuilder::new(this.base_url.clone()))
});
// methods.add_async_method("get", |lua, this, path: String| async move {
// let url = this.build_url(path);
//
// let client = reqwest::Client::new();
//
// let response = client
// .get(&url)
// .send()
// .await
// .map_err(|e| mlua::Error::RuntimeError(e.to_string()))?;
//
// let status = response.status().as_u16();
// let text = response
// .text()
// .await
// .map_err(|e| mlua::Error::RuntimeError(e.to_string()))?;
//
// let json: Option<JsonValue> = serde_json::from_str(&text).ok();
//
// let res_table = lua.create_table()?;
// res_table.set("status", status)?;
// res_table.set("body", text)?;
//
// if let Some(json_val) = json {
// let lua_json = json_to_lua(&lua, json_val)?;
// res_table.set("json", lua_json.clone())?;
// }
// Ok(res_table)
// });
}
}
pub fn json_to_lua(lua: &Lua, value: JsonValue) -> Result<mlua::Value, mlua::Error> {
Ok(match value {
JsonValue::Null => mlua::Value::Nil,
JsonValue::Bool(b) => mlua::Value::Boolean(b),
JsonValue::Number(n) => {
if let Some(i) = n.as_i64() {
mlua::Value::Integer(i)
} else if let Some(f) = n.as_f64() {
mlua::Value::Number(f)
} else {
mlua::Value::Nil
}
}
JsonValue::String(s) => mlua::Value::String(lua.create_string(&s)?),
JsonValue::Array(arr) => {
let table = lua.create_table()?;
for (i, v) in arr.into_iter().enumerate() {
table.set(i + 1, json_to_lua(lua, v)?)?;
}
mlua::Value::Table(table)
}
JsonValue::Object(obj) => {
let table = lua.create_table()?;
for (k, v) in obj {
table.set(k, json_to_lua(lua, v)?)?;
}
mlua::Value::Table(table)
}
})
}