we hav haz lua
This commit is contained in:
1049
Cargo.lock
generated
1049
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@ opt-level = "z"
|
||||
file-format = "0.24"
|
||||
axum = { version = "0.7", features = [] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tera = { version = "1.19", features = [] }
|
||||
tokio = { version = "1.37", features = ["full"] }
|
||||
tokio-stream = { version = "0.1", features = ["full"] }
|
||||
@@ -24,3 +25,11 @@ exe = "0.5"
|
||||
image = { version = "0.25", features = ["ico"] }
|
||||
urlencoding = "2.1"
|
||||
markdown = "1.0.0-alpha.16"
|
||||
mlua = { version = "0.9", features = [
|
||||
"lua54",
|
||||
"vendored",
|
||||
"serialize",
|
||||
"async",
|
||||
"send",
|
||||
] }
|
||||
reqwest = { version = "0.10", features = ["json", "rustls-tls", "blocking"] }
|
||||
|
182
src/main.rs
182
src/main.rs
@@ -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> {
|
||||
|
Reference in New Issue
Block a user