summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2026-03-05 00:52:03 -0500
committerJohn Turner <jturner.usa@gmail.com>2026-03-05 00:52:03 -0500
commit92e8d4947de614a67fed6709a59365de98705b35 (patch)
tree981213f1ed73c88834f9ec3fe7c9b1b8f3e19211 /src
parent583a62c4a2ac6137134d50f70ff8ad546ac4b2a1 (diff)
downloadhttpd-92e8d4947de614a67fed6709a59365de98705b35.tar.gz
impl Lua handler
Diffstat (limited to 'src')
-rw-r--r--src/handler.rs12
-rw-r--r--src/handler/lua.rs75
-rw-r--r--src/main.rs1
3 files changed, 87 insertions, 1 deletions
diff --git a/src/handler.rs b/src/handler.rs
index 45dc879..eb4d64a 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -1,8 +1,13 @@
+mod lua;
mod staticfile;
use mlua::{FromLua, Value};
-use crate::{handler::staticfile::StaticFile, request::Request, response::Response};
+use crate::{
+ handler::{lua::LuaResponse, staticfile::StaticFile},
+ request::Request,
+ response::Response,
+};
pub trait Handle {
fn handle(self, request: Request) -> impl Future<Output = Result<Response, Error>>;
@@ -20,6 +25,7 @@ pub enum Error {
#[derive(Debug)]
pub enum Handler {
StaticFile(StaticFile),
+ Lua(LuaResponse),
}
impl FromLua for Handler {
@@ -30,6 +36,10 @@ impl FromLua for Handler {
Value::Table(table.clone()),
lua,
)?)),
+ "lua" => Ok(Self::Lua(LuaResponse::from_lua(
+ Value::Table(table.clone()),
+ lua,
+ )?)),
_ => Err(mlua::Error::runtime("unknown handler")),
},
_ => Err(mlua::Error::runtime("expected table")),
diff --git a/src/handler/lua.rs b/src/handler/lua.rs
new file mode 100644
index 0000000..377111f
--- /dev/null
+++ b/src/handler/lua.rs
@@ -0,0 +1,75 @@
+use std::{collections::HashMap, str::FromStr};
+
+use mlua::{FromLua, Lua, Value};
+
+use crate::{
+ handler::{self, Handle},
+ request::Request,
+ response::{Body, Response, Status},
+};
+
+#[derive(Debug, Clone)]
+pub struct LuaResponse {
+ content: Option<Vec<u8>>,
+ status: Status,
+ headers: HashMap<String, Vec<u8>>,
+}
+
+impl Handle for LuaResponse {
+ async fn handle(self, _: Request) -> Result<Response, handler::Error> {
+ Ok(Response::builder()
+ .status(self.status)
+ .headers(self.headers)
+ .body(match self.content {
+ Some(content) => Body::Buffer(content),
+ None => Body::Empty,
+ }))
+ }
+}
+
+impl FromLua for LuaResponse {
+ fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
+ match value {
+ Value::Table(table) => {
+ let content = match table.get("content")? {
+ Value::String(string) => Some(string.as_bytes().to_vec()),
+ _ => None,
+ };
+
+ let status = match table.get("status")? {
+ Value::String(string) => Status::from_str(&string.to_str()?).map_err(|e| {
+ mlua::Error::RuntimeError(format!(
+ "failed to parse status from string: {e}"
+ ))
+ })?,
+ Value::Integer(i) => Status::from_repr(i as usize).ok_or_else(|| {
+ mlua::Error::runtime(format!("failed to parse status from integer: {i}"))
+ })?,
+ _ => return Err(mlua::Error::runtime("invalid type when reading status")),
+ };
+
+ let headers: HashMap<String, Vec<u8>> = match table.get::<Value>("headers")? {
+ Value::Table(table) => {
+ let mut hashmap = HashMap::<String, Vec<u8>>::new();
+
+ for result in table.pairs() {
+ let (key, value): (String, mlua::BString) = result?;
+
+ hashmap.insert(key, value.to_vec());
+ }
+
+ hashmap
+ }
+ _ => HashMap::new(),
+ };
+
+ Ok(Self {
+ content,
+ status,
+ headers,
+ })
+ }
+ _ => Err(mlua::Error::runtime("expected table")),
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 3d69f36..6d89a0d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -83,6 +83,7 @@ async fn handle(handlers: Table, request: Request) -> Result<Response, HandleErr
match handler {
Handler::StaticFile(staticfile) => Ok(staticfile.handle(request).await?),
+ Handler::Lua(lua_response) => Ok(lua_response.handle(request).await?),
}
}