mirror of
https://github.com/DefectingCat/candy
synced 2025-07-15 16:51:34 +00:00
feat: impl lua engine
This commit is contained in:
@ -6,15 +6,22 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use axum_extra::extract::Host;
|
use axum_extra::extract::Host;
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
|
use mlua::{UserData, Value};
|
||||||
|
use tokio::fs::{self};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
http::{HOSTS, error::RouteError, serve::resolve_parent_path},
|
http::{HOSTS, LUA_ENGINE, error::RouteError, serve::resolve_parent_path},
|
||||||
utils::parse_port_from_host,
|
utils::parse_port_from_host,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::error::RouteResult;
|
use super::error::RouteResult;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct Candy {}
|
||||||
|
|
||||||
|
impl UserData for Candy {}
|
||||||
|
|
||||||
pub async fn lua(
|
pub async fn lua(
|
||||||
req_uri: Uri,
|
req_uri: Uri,
|
||||||
path: Option<Path<String>>,
|
path: Option<Path<String>>,
|
||||||
@ -44,6 +51,16 @@ pub async fn lua(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(RouteError::InternalError())
|
.ok_or(RouteError::InternalError())
|
||||||
.with_context(|| "lua script not found")?;
|
.with_context(|| "lua script not found")?;
|
||||||
error!("Lua script: {lua_script}");
|
|
||||||
|
let lua = &LUA_ENGINE.lua;
|
||||||
|
let script = fs::read_to_string(lua_script)
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("Failed to read lua script file: {lua_script}",))?;
|
||||||
|
let data: Value = lua.load(script).eval_async().await.map_err(|err| {
|
||||||
|
error!("Lua script {lua_script} exec error: {err}");
|
||||||
|
RouteError::InternalError()
|
||||||
|
})?;
|
||||||
|
tracing::debug!("Lua script: {data:?}");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
use std::{net::SocketAddr, sync::LazyLock, time::Duration};
|
use std::{
|
||||||
|
net::SocketAddr,
|
||||||
|
sync::{Arc, LazyLock},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::{Context, anyhow};
|
||||||
use axum::{Router, extract::DefaultBodyLimit, middleware, routing::get};
|
use axum::{Router, extract::DefaultBodyLimit, middleware, routing::get};
|
||||||
use axum_server::{Handle, tls_rustls::RustlsConfig};
|
use axum_server::{Handle, tls_rustls::RustlsConfig};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use mlua::Lua;
|
use mlua::{Lua, Value};
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_http::{compression::CompressionLayer, timeout::TimeoutLayer};
|
use tower_http::{compression::CompressionLayer, timeout::TimeoutLayer};
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
@ -36,8 +40,70 @@ pub mod lua;
|
|||||||
/// }
|
/// }
|
||||||
pub static HOSTS: LazyLock<DashMap<u16, SettingHost>> = LazyLock::new(DashMap::new);
|
pub static HOSTS: LazyLock<DashMap<u16, SettingHost>> = LazyLock::new(DashMap::new);
|
||||||
|
|
||||||
|
pub struct LuaEngine {
|
||||||
|
pub lua: Lua,
|
||||||
|
pub shared_table: Arc<DashMap<String, String>>,
|
||||||
|
}
|
||||||
|
impl LuaEngine {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let lua = Lua::new();
|
||||||
|
let shared_table: DashMap<String, String> = DashMap::new();
|
||||||
|
let shared_table = Arc::new(shared_table);
|
||||||
|
|
||||||
|
let module = lua.create_table().expect("create table failed");
|
||||||
|
let shared_api = lua.create_table().expect("create shared table failed");
|
||||||
|
|
||||||
|
// 创建共享字典到 lua 中
|
||||||
|
let shared_table_get = shared_table.clone();
|
||||||
|
shared_api
|
||||||
|
.set(
|
||||||
|
"set",
|
||||||
|
lua.create_function(move |_, (key, value): (String, String)| {
|
||||||
|
let t = shared_table_get
|
||||||
|
.insert(key, value.clone())
|
||||||
|
.ok_or(anyhow!("key not found"))?;
|
||||||
|
Ok(t.clone())
|
||||||
|
})
|
||||||
|
.expect("create set function failed"),
|
||||||
|
)
|
||||||
|
.expect("set failed");
|
||||||
|
let shared_table_get = shared_table.clone();
|
||||||
|
shared_api
|
||||||
|
.set(
|
||||||
|
"get",
|
||||||
|
lua.create_function(move |_, key: String| {
|
||||||
|
let t = shared_table_get.get(&key).ok_or(anyhow!("key not found"))?;
|
||||||
|
Ok(t.clone())
|
||||||
|
})
|
||||||
|
.expect("create get function failed"),
|
||||||
|
)
|
||||||
|
.expect("get failed");
|
||||||
|
module
|
||||||
|
.set("shared", shared_api)
|
||||||
|
.expect("set shared_api failed");
|
||||||
|
|
||||||
|
// 日志函数
|
||||||
|
module
|
||||||
|
.set(
|
||||||
|
"log",
|
||||||
|
lua.create_function(move |_, msg: String| {
|
||||||
|
tracing::info!("Lua: {}", msg);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.expect("create log function failed"),
|
||||||
|
)
|
||||||
|
.expect("set log failed");
|
||||||
|
|
||||||
|
// 全局变量 candy
|
||||||
|
lua.globals()
|
||||||
|
.set("candy", module)
|
||||||
|
.expect("set candy failed");
|
||||||
|
|
||||||
|
Self { lua, shared_table }
|
||||||
|
}
|
||||||
|
}
|
||||||
/// lua 脚本执行器
|
/// lua 脚本执行器
|
||||||
pub static LUA_EXECUTOR: LazyLock<Lua> = LazyLock::new(Lua::new);
|
pub static LUA_ENGINE: LazyLock<LuaEngine> = LazyLock::new(LuaEngine::new);
|
||||||
|
|
||||||
pub async fn make_server(host: SettingHost) -> anyhow::Result<()> {
|
pub async fn make_server(host: SettingHost) -> anyhow::Result<()> {
|
||||||
let mut router = Router::new();
|
let mut router = Router::new();
|
||||||
|
Reference in New Issue
Block a user