we hav haz lua

This commit is contained in:
2024-08-31 15:05:26 +02:00
parent bdaf9aa1ba
commit 67c5bb6837
3 changed files with 1121 additions and 119 deletions

View File

@@ -3,12 +3,13 @@ mod icon;
use std::{collections::HashMap, fs, io::ErrorKind, path::PathBuf, str::FromStr};
use icon::extract_icon;
use mlua::{Lua, Table, Value as LuaValue};
use once_cell::sync::{Lazy, OnceCell};
use axum::{
extract::Request,
handler::HandlerWithoutStateExt,
http::StatusCode,
http::{HeaderName, HeaderValue, StatusCode},
response::{Html, IntoResponse},
routing::get,
};
@@ -177,8 +178,6 @@ async fn file_handler(request: Request) -> impl IntoResponse {
PathBuf::from_str(&std::env::var("BASE_DIR").unwrap_or(String::from("./public"))).unwrap()
});
dbg!(&request);
if !request.uri().path().ends_with(".lua") {
return ServeDir::new(base_dir)
.fallback(get(handler))
@@ -188,12 +187,179 @@ async fn file_handler(request: Request) -> impl IntoResponse {
.map_err(|_| StatusCode::NOT_FOUND);
};
// TODO: process file as lua, where everything "printed" and or "returned" from the file is presented on screen
// OR, prints go to console, return from main script goes to screen
// Also need to be able to set content-type etc from within lua
let lua = Lua::new();
let globals = lua.globals();
// Ok(Html("Rawr").into_response())
Err(StatusCode::NOT_IMPLEMENTED)
use mlua::{ExternalResult, LuaSerdeExt};
let fetch_json = lua
.create_function(|lua, uri: String| {
let resp = reqwest::blocking::get(&uri)
.and_then(|resp| resp.error_for_status())
.into_lua_err()?;
let json = resp.json::<serde_json::Value>().into_lua_err()?;
lua.to_value(&json)
})
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let dbg = lua
.create_function(|_, value: LuaValue| {
dbg!(value);
Ok(())
})
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
globals.set("fetch", fetch_json).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
globals.set("dbg", dbg).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let request_table = lua.create_table().map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let headers_table = lua
.create_table_from(
request
.headers()
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_str().unwrap())),
)
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
request_table.set("headers", headers_table).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
request_table
.set("uri", request.uri().to_string())
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
request_table
.set("method", request.method().to_string())
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
// Inject functions to change headers and such
globals.set("request", request_table).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let response_table = lua.create_table().map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
response_table
.set(
"headers",
lua.create_table().map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?,
)
.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
globals.set("response", response_table).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let mut path = base_dir.clone();
let uri = urlencoding::decode(&request.uri().path()[1..]).map_err(|e| {
println!("{:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
path.push(&*uri);
let full_path = fs::canonicalize(&path).map_err(|e| {
println!("{:?}", e);
StatusCode::NOT_FOUND
})?;
let full_base_path = fs::canonicalize(base_dir).map_err(|e| {
println!("{:?}", e);
StatusCode::NOT_FOUND
})?;
if !full_path.starts_with(full_base_path) {
return Err(StatusCode::BAD_REQUEST);
}
let script = fs::read_to_string(full_path).map_err(|e| {
eprintln!("Lua Read Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let script = lua.load(script).eval::<LuaValue>().map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let result = lua.load("return response").eval::<Table>().map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
let script = if let LuaValue::String(script) = script {
script.to_string_lossy().to_string()
} else {
serde_json::to_string(&script).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?
};
let mut response = Html(script).into_response();
if let Ok(headers) = result.get::<&str, Table>("headers") {
let pairs = headers.pairs::<String, String>();
for pair in pairs {
let (k, v) = pair.map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
response.headers_mut().insert(
HeaderName::from_str(&k).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?,
HeaderValue::from_str(&v).map_err(|e| {
eprintln!("Lua Error: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?,
);
}
};
Ok(response)
}
async fn handler(request: Request) -> Result<Html<String>, StatusCode> {