summaryrefslogtreecommitdiff
path: root/htmlua-parser
diff options
context:
space:
mode:
authorgyoder <70408179+gyoder@users.noreply.github.com>2025-07-11 12:19:26 -0600
committergyoder <70408179+gyoder@users.noreply.github.com>2025-07-11 12:19:26 -0600
commit4144fa2cba9732c1cee39b44b38f3752aefc4c03 (patch)
tree5d6434b1f6f85591a448fc28d53b7e4f712c7b66 /htmlua-parser
parentc8ffbb2af0eae39b897ff3b1b6c8263181fdd8d4 (diff)
Added Basic HTTP stdlibhttpstdlib
Diffstat (limited to 'htmlua-parser')
-rw-r--r--htmlua-parser/Cargo.toml5
-rw-r--r--htmlua-parser/src/htmlua_stdlib.rs151
-rw-r--r--htmlua-parser/src/lib.rs1
-rw-r--r--htmlua-parser/src/render.rs25
4 files changed, 157 insertions, 25 deletions
diff --git a/htmlua-parser/Cargo.toml b/htmlua-parser/Cargo.toml
index 28416b7..83769af 100644
--- a/htmlua-parser/Cargo.toml
+++ b/htmlua-parser/Cargo.toml
@@ -8,8 +8,11 @@ anyhow = "1.0.98"
html5ever = "0.35.0"
kuchikiki = "0.8.2"
markup5ever = "0.11.0"
-mlua = { version = "0.10.5", features = ["lua54", "vendored", "serialize"] }
+mlua = { version = "0.10.5", features = ["lua54", "vendored", "serialize", "anyhow"] }
pulldown-cmark = "0.13.0"
+reqwest = { version = "0.12.22", features = ["blocking", "json"] }
+serde = { version = "1.0.219", features = ["derive"] }
+serde_json = "1.0.140"
syntect = "5.2.0"
tendril = "0.4.3"
diff --git a/htmlua-parser/src/htmlua_stdlib.rs b/htmlua-parser/src/htmlua_stdlib.rs
new file mode 100644
index 0000000..3c27f26
--- /dev/null
+++ b/htmlua-parser/src/htmlua_stdlib.rs
@@ -0,0 +1,151 @@
+use std::{cell::{LazyCell, RefCell}, collections::HashMap, fmt::Write, rc::Rc};
+
+use anyhow::anyhow;
+use mlua::{prelude::*, Error, Lua, Table};
+use reqwest::{blocking::{Client, Response}, header::HeaderMap};
+use serde::{Deserialize, Serialize};
+use serde_json::to_value;
+
+
+pub fn create_htmlua_stdlib(l: &Lua, stdout: &Rc<RefCell<String>>) -> mlua::Result<Table> {
+ let t = l.create_table()?;
+
+ // This cannot be the best way to do this
+
+ let stdout_println = stdout.clone();
+ t.set(
+ "println",
+ l.create_function(move |_, text: String| {
+ let mut stdout_ref = stdout_println.borrow_mut();
+ writeln!(stdout_ref, "{text}").map_err(mlua::Error::external)
+ })?,
+ )?;
+
+ let stdout_print = stdout.clone();
+ t.set(
+ "print",
+ l.create_function(move |_, text: String| {
+ let mut stdout_ref = stdout_print.borrow_mut();
+ write!(stdout_ref, "{text}").map_err(mlua::Error::external)
+ })?,
+ )?;
+
+ t.set("http", create_http_lib(l)?)?;
+ Ok(t)
+}
+
+fn create_http_lib(l: &Lua) -> mlua::Result<Table> {
+ let t = l.create_table()?;
+ let http_client: Rc<LazyCell<Client>> = Rc::new(LazyCell::new(|| Client::builder()
+ .timeout(std::time::Duration::from_secs(3))
+ .user_agent("htmlua/0.1.0")
+ .build().unwrap()
+ ));
+
+
+ let client = http_client.clone();
+ t.set(
+ "get",
+ l.create_function(move |_, url: String| {
+ let res = client.get(url).send().map_err(|e| Error::RuntimeError(e.to_string()))?;
+ let lua_res: LuaHttpResponse = TryFrom::try_from(res)?;
+ Ok(lua_res)
+ })?
+ )?;
+
+ let client = http_client.clone();
+ t.set(
+ "post",
+ l.create_function(move |_, url: String| {
+ let res = client.post(url).send().map_err(|e| Error::RuntimeError(e.to_string()))?;
+ let lua_res: LuaHttpResponse = TryFrom::try_from(res)?;
+ Ok(lua_res)
+ })?
+ )?;
+
+ let client = http_client.clone();
+ t.set(
+ "get_with_data",
+ l.create_function(move |_, (url, data): (String, HashMap<String, String>)| {
+ let res = client.get(url).query(&data).send().map_err(|e| Error::RuntimeError(e.to_string()))?;
+ let lua_res: LuaHttpResponse = TryFrom::try_from(res)?;
+ Ok(lua_res)
+ })?
+ )?;
+
+ let client = http_client.clone();
+ t.set(
+ "post_with_data_form",
+ l.create_function(move |_, (url, data): (String, HashMap<String, String>)| {
+ let res = client.post(url).form(&data).send().map_err(|e| Error::RuntimeError(e.to_string()))?;
+ let lua_res: LuaHttpResponse = TryFrom::try_from(res)?;
+ Ok(lua_res)
+ })?
+ )?;
+
+ let client = http_client.clone();
+ t.set(
+ "post_with_data_json",
+ l.create_function(move |_, (url, data): (String, HashMap<String, String>)| {
+ let res = client.post(url).json(&data).send().map_err(|e| Error::RuntimeError(e.to_string()))?;
+ let lua_res: LuaHttpResponse = TryFrom::try_from(res)?;
+ Ok(lua_res)
+ })?
+ )?;
+ //TODO: all http
+
+ t.set(
+ "decode_json",
+ l.create_function(move |l, text: String| {
+ let table: serde_json::Value = serde_json::from_str(&text).map_err(|e| Error::RuntimeError(e.to_string()))?;
+ Ok(l.to_value(&table))
+ })?
+ )?;
+
+ Ok(t)
+}
+
+
+#[derive(Serialize, Deserialize)]
+struct LuaHttpResponse {
+ headers: HashMap<String, String>,
+ body: String,
+ status: u16,
+}
+
+impl TryFrom<Response> for LuaHttpResponse {
+ fn try_from(value: Response) -> Result<Self, Self::Error> {
+ Ok(LuaHttpResponse { headers: headermap_to_hashmap(value.headers()), status: value.status().as_u16(), body: value.text().map_err(|e| Error::RuntimeError(e.to_string()))?, })
+ }
+
+ type Error = Error;
+}
+
+fn headermap_to_hashmap(headers: &HeaderMap) -> HashMap<String, String> {
+ let mut map = HashMap::new();
+
+ for (name, value) in headers {
+ if let Ok(value_str) = value.to_str() {
+ map.insert(name.as_str().to_string(), value_str.to_string());
+ }
+ }
+
+ map
+}
+
+impl IntoLua for LuaHttpResponse {
+ fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
+ let table = lua.create_table()?;
+
+ table.set("status", self.status)?;
+ table.set("body", self.body)?;
+
+ let headers_table = lua.create_table()?;
+ for (key, value) in self.headers {
+ headers_table.set(key, value)?;
+ }
+ table.set("headers", headers_table)?;
+
+ Ok(LuaValue::Table(table))
+ }
+}
diff --git a/htmlua-parser/src/lib.rs b/htmlua-parser/src/lib.rs
index cd87be2..be272dd 100644
--- a/htmlua-parser/src/lib.rs
+++ b/htmlua-parser/src/lib.rs
@@ -1,3 +1,4 @@
pub mod render;
pub mod serve;
pub mod helpers;
+pub mod htmlua_stdlib;
diff --git a/htmlua-parser/src/render.rs b/htmlua-parser/src/render.rs
index 6444d60..1bb043b 100644
--- a/htmlua-parser/src/render.rs
+++ b/htmlua-parser/src/render.rs
@@ -12,32 +12,9 @@ use syntect::{
util::LinesWithEndings,
};
-use crate::helpers::read_doc_from_file;
+use crate::{helpers::read_doc_from_file, htmlua_stdlib::create_htmlua_stdlib};
-fn create_htmlua_stdlib(l: &Lua, stdout: &Rc<RefCell<String>>) -> mlua::Result<Table> {
- let t = l.create_table()?;
- // This cannot be the best way to do this
-
- let stdout_println = stdout.clone();
- t.set(
- "println",
- l.create_function(move |_, text: String| {
- let mut stdout_ref = stdout_println.borrow_mut();
- writeln!(stdout_ref, "{text}").map_err(mlua::Error::external)
- })?,
- )?;
-
- let stdout_print = stdout.clone();
- t.set(
- "print",
- l.create_function(move |_, text: String| {
- let mut stdout_ref = stdout_print.borrow_mut();
- write!(stdout_ref, "{text}").map_err(mlua::Error::external)
- })?,
- )?;
- Ok(t)
-}
pub fn execute_lua(document: NodeRef) -> Result<NodeRef> {
let lua = Lua::new();